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

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

import com.ffii.core.dao.JdbcDao;
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.file.FileBlob;
import com.ffii.tbms.file.FileRef;
import com.ffii.tbms.file.service.FileService;

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


@Service
public class SysGroupService extends AbstractService {

	@Autowired
	private JdbcDao jdbcDao;

	@Autowired
	private FileService fileService;

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

		args.put("deleted", Boolean.FALSE);
		args.put("versionId", 0);
		args.put("created", new Date());
		args.put("createdBy", SecurityUtils.getUser().getId());
		args.put("modified", new Date());
		args.put("modifiedBy", SecurityUtils.getUser().getId());
		
		return jdbcDao.executeInsertAndReturnKey("sys_groups", "id", args).intValue();
	}

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

		args.put("modified", new Date());
		args.put("modifiedBy", SecurityUtils.getUser().getId());

		String sql = "UPDATE sys_groups SET ";
		if(args.containsKey("deleted")){
			sql+=" deleted = :deleted, ";
		}
		if(args.containsKey("name")){
			sql+=" name = :name, ";
		}
		if(args.containsKey("companyName")){
			sql+=" companyName = :companyName, ";
		}
		if(args.containsKey("phone")){
			sql+=" phone = :phone, ";
		}
		if(args.containsKey("fax")){
			sql+=" fax = :fax, ";
		}
		if(args.containsKey("email")){
			sql+=" email = :email, ";
		}
		if(args.containsKey("address")){
			sql+=" address = :address, ";
		}
		if(args.containsKey("smtp_host")){
			sql+=" smtp_host = :smtp_host, ";
		}
		if(args.containsKey("smtp_port")){
			sql+=" smtp_port = :smtp_port, ";
		}
		if(args.containsKey("smtp_username")){
			sql+=" smtp_username = :smtp_username, ";
		}
		if(args.containsKey("smtp_password")){
			sql+=" smtp_password = :smtp_password, ";
		}
		sql += " modified = :modified, modifiedBy = :modifiedBy WHERE id = :id ";
		return jdbcDao.executeUpdate(sql,args);
	}

	@Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = true)
	public Map<String, Object> find(Integer id) {
		logger.info("sys_groups: "+id);
		Map<String, Object> args = MapUtils.toHashMap("id", id);
		
		StringBuilder sql = new StringBuilder(
			" SELECT sg.* FROM sys_groups sg WHERE sg.id = :id "
		);

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

	@Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = true)
	public List<Map<String, Object>> search(Map<String, Object> args) {
		
		StringBuilder sql = new StringBuilder("SELECT "
		+" sg.*, "
		+" userCount.count AS userCount "
		+" FROM sys_groups sg "
		+" LEFT JOIN "
		+" (SELECT "
		+" u.sysGroupId, COUNT(id) AS count "
		+" FROM "
		+" 	users u "
		+" GROUP BY u.sysGroupId) "
		+" userCount ON userCount.sysGroupId = sg.id"
		+" WHERE 1=1 ");

		if(args.containsKey("deleted")){
			sql.append(" AND sg.deleted = :deleted ");
		}
		if(args.containsKey("name")){
			sql.append(" AND sg.name LIKE :name ");
		}

		if (args.containsKey(Params.QUERY)) sql.append(" AND (sg.name LIKE :query)");

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

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

		StringBuilder sql = new StringBuilder("SELECT"
				+ " g.id,"
				+ " g.name AS groupName"
				+ " FROM groups g"
				+ " WHERE g.deleted = 0");

		if (args.containsKey(Params.QUERY)) sql.append(" AND (g.name LIKE :query)");

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

		sql.append(" ORDER BY g.name");

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

	@Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = false)
	public FileRef getIconFileRef(){
		 return fileService.findFileRefByTypeAndId("SysGroupIcon", SecurityUtils.getUser().getSysGroupId());
	}

	@Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = false)
	public FileBlob getIconBlob(){
		FileRef ref = getIconFileRef();
		if(ref == null) return null;
		FileBlob blob = fileService.findFileBlobByFileId(ref.getFileId());
		return blob;
	}

}
