/*******************************************************************************
 * Copyright 2019 2Fi Business Solutions Ltd.
 *
 *
 *
 * This code is copyrighted. Under no circumstances should any party, people,
 * or organization should redistribute any portions of this code in any form,
 * either verbatim or through electronic media, to any third parties, unless
 * under explicit written permission by 2Fi Business Solutions Ltd.
 ******************************************************************************/
package com.ffii.tbms.example.service;

import java.util.Date;
import java.util.List;
import java.util.Map;

import com.ffii.core.dao.JdbcDao;
import com.ffii.core.utils.DateUtils;
import com.ffii.core.utils.ExcelUtils;
import com.ffii.core.utils.JsonUtils;
import com.ffii.core.utils.MapUtils;
import com.ffii.core.utils.Params;
import com.ffii.core.utils.SecurityUtils;
import com.ffii.core.web.AbstractService;
import com.ffii.tbms.example.Example;
import com.ffii.tbms.example.dao.ExampleDao;
import com.ffii.tbms.file.service.FileService;
import com.ffii.tbms.log.service.AuditLogService;

import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ResourceLoader;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

/**
 * Example Service
 *
 * @author Patrick
 */
@Service
public class ExampleService extends AbstractService {

	@Autowired
	private JdbcDao jdbcDao;

	@Autowired
	private ExampleDao exampleDao;

	@Autowired
	private FileService fileService;

	@Autowired
	private ResourceLoader resourceLoader;

	@Autowired
	private AuditLogService auditLogService;

	@Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = false)
	public Integer saveExample(Example instance) {
		return exampleDao.saveOrUpdate(instance);
	}

	@Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = false)
	public int insertSomething(Map<String, Object> args) {
		return jdbcDao.executeInsertAndReturnKey("example", Params.ID, args).intValue();
	}

	@Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = false)
	public void updateStatusWithAuditLog() {
		Map<String, Object> args = MapUtils.toHashMap(Params.ID, 1, "status", "pig", "mode", "B");
		int rs = jdbcDao.executeUpdateByTable("job", args);

		if (rs > 0) auditLogService.save("job", 1, SecurityUtils.getUser().getId(), new Date(), null, JsonUtils.toJsonString(args));
	}

	@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class, readOnly = true)
	public List<Map<String, Object>> search(Map<String, Object> args) {

		String sql = "SELECT 1";

		return jdbcDao.queryForList(sql, args);
	}

	/**
	 * Scheduled method example using cron expression<br>
	 * 1. return type must be void<br>
	 * 2. must not have any parameters<br>
	 *
	 * <p>
	 * Cron expression:<br>
	 * 1. Seconds: 0-59<br>
	 * 2. Minutes: 0-59<br>
	 * 3. Hours: 0-23<br>
	 * 4. Day of month: 1-31<br>
	 * 5. Month: 0-11 = Jan to Dec<br>
	 * 6. Day of week: 1-7 = Sunday to Saturday<br>
	 */
	@Scheduled(cron = "0 5 0 * * ?") // everyday at 00:05:00
	public void scheduledMethodCron() {
		logger.info("scheduledMethodCron at 00:05:00");
	}

	@Scheduled(cron = "0 0 12 * * ?") // everyday at noon 12:00:00
	public void scheduledExcelReports() {
		Workbook workbook = ExcelUtils.loadXSSFWorkbookFromTemplateSource(resourceLoader, "WEB-INF/report/exampleTemplate.xlsx");
		Sheet sheet = workbook.getSheetAt(0);

		int colIndex = 1;
		for (int i = 0; i < 10; i++) {
			ExcelUtils.setCellValue(sheet, i, colIndex, i);
		}

		// save the Excel file
		byte[] bytes = ExcelUtils.toByteArray(workbook);
		fileService.saveFile("Example_Report_" + DateUtils.SQL_DATE_FORMAT.format(new Date()), "", "exampleReport", 0, "", bytes);
	}

	/**
	 * Scheduled method example using fixed rate<br>
	 * 1. return type must be void<br>
	 * 2. must not have any parameters<br>
	 *
	 * fixedRate in ms, e.g. 60000ms = run every 60 seconds
	 */
	@Scheduled(fixedRate = 60000)
	public void scheduledMethodFixedRate() {
		logger.debug("scheduledMethodFixedRate at 60000ms");
	}

}