/*******************************************************************************
 * Copyright 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.meeting.service;

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

import com.ffii.core.dao.JdbcDao;
import com.ffii.core.utils.BooleanUtils;
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.meeting.Meeting;
import com.ffii.tbms.meeting.dao.MeetingDao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author Patrick
 */
@Service
public class MeetingService extends AbstractService {

	@Autowired
	private JdbcDao jdbcDao;

	@Autowired
	private MeetingDao meetingDao;

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

	@Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = true)
	public Meeting find(Integer id) {
		return meetingDao.find(id);
	}

	private String getSearchCriteriaString(Map<String, Object> args) {
		StringBuilder sql = new StringBuilder("");

		if (args != null) {
			if (args.containsKey("fromDate"))
				sql.append(" AND DATE(m.date) >= DATE(:fromDate) ");
			if (args.containsKey("toDate"))
				sql.append(" AND DATE(m.date) < :toDate ");
			if (args.containsKey("custId"))
				sql.append(" AND m.custId = :custId ");
			if (args.containsKey("orderId"))
				sql.append(" AND m.orderId = :orderId ");

			if (args.containsKey(Params.ID))
				sql.append(" AND m.id = :id");

			if(args.containsKey("sysGroupId")){
				sql.append(" AND m.sysGroupId = :sysGroupId ");
			}
		}

		return sql.toString();
	}

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

		SecurityUtils.authArgs(args);

		StringBuilder sql = new StringBuilder(" SELECT "
				+ " m.*, "
				+ " concat_ws(' / ', c.phone1, c.phone2) AS phone, "
				+ " c.email, "
				+ " concat(o.type,' ',o.code) AS orderNo , "
				+ " CONCAT(IF(c.firstName IS NULL, '', CONCAT(c.firstName, ' ')), "
				+ " IF(c.surname IS NULL, '', CONCAT(c.surname, ' ')), "
				+ " IF(c.nameCh IS NULL, '', c.nameCh)) AS customerName "
				+ " FROM meeting m "
				+ " LEFT JOIN customer c ON c.id = m.custId "
				+ " LEFT JOIN orders o ON o.id = m.orderId "
				+ " WHERE m.deleted = 0 ");

		sql.append(getSearchCriteriaString(args));

		if(args.containsKey("sysGroupId")){
			sql.append(" AND m.sysGroupId = :sysGroupId ");
		}

		if (args.containsKey("meetingDate")) {
			sql.append(" AND DATE(m.date) = :meetingDate");
		}

		if (args.containsKey("isDESC") && BooleanUtils.isTrue(args.get("isDESC"))) {
			sql.append(" ORDER BY m.date DESC, m.id DESC ");
		}else{
			sql.append(" ORDER BY m.date ASC, m.id ASC ");
		}

		if (args != null) {
			if (args.containsKey("start") && args.containsKey("limit"))
				sql.append(" LIMIT :start, :limit");
		}
		logger.info(sql.toString());

		return jdbcDao.queryForList(sql.toString(), args);
	}

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

		SecurityUtils.authArgs(args);

		StringBuilder sql = new StringBuilder(" SELECT count(*) AS count FROM meeting m WHERE m.deleted = 0 ");

		sql.append(getSearchCriteriaString(args));
		if(args.containsKey("sysGroupId")){
			sql.append(" AND m.sysGroupId = :sysGroupId ");
		}
		if (args.containsKey("meetingDate")) {
			sql.append(" AND m.date = :meetingDate");
		}

		return jdbcDao.queryForMap(sql.toString(), args);
	}

	@Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = true)
	public Map<String, Object> queryForMap(Integer id) {

		Map<String, Object> args = MapUtils.toHashMap(Params.ID, id);
		SecurityUtils.authArgs(args);

		String sql = "SELECT * FROM meeting m WHERE m.id = :id";

		if(args.containsKey("sysGroupId")){
			sql+=" AND m.sysGroupId = :sysGroupId ";
		}

		return jdbcDao.queryForMap(sql, args);
	}

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

		SecurityUtils.authArgs(args);

		StringBuilder sql = new StringBuilder("SELECT Date(m.date) as date, "
			+ " SUM(IF(type = " + Meeting.TYPE_COMMISSION + ", 1, 0)) AS commission, "
			+ " SUM(IF(type = " + Meeting.TYPE_FITTING + ", 1, 0)) AS fitting, "
			+ " SUM(IF(type = " + Meeting.TYPE_PICKUP + ", 1, 0)) AS pickup, "
			+ " SUM(IF(type = " + Meeting.TYPE_NEW + ", 1, 0)) AS new "
			+ " FROM meeting m "
			+ " WHERE m.deleted = 0 ");

			if(args.containsKey("sysGroupId")){
				sql.append(" AND m.sysGroupId = :sysGroupId ");
			}

		sql.append(getSearchCriteriaString(args));

		sql.append(" GROUP BY DATE(m.date) ORDER BY DATE(m.date) DESC ");

		logger.info("searchForCalendar:"+sql.toString());
		logger.info("args:"+args);

		return jdbcDao.queryForList(sql.toString(), args);
	}

	public void addActionLog(int refId, String table, String recordStr){

	}

}
