package com.platform.service.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import net.sf.json.regexp.RegexpUtils;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.platform.dao.PreDataInfoDao;
import com.platform.entities.DefaultDataDescription;
import com.platform.entities.MyFilesEntity;
import com.platform.entities.PreDataInfo;
import com.platform.service.IScriptMakeService;
import com.platform.utils.BeanCopy;
import com.platform.utils.Compare4MyFilesEntity;
import com.platform.utils.Configs;
import com.platform.utils.Constant;
import com.platform.utils.FileOperateHelper;
import com.platform.utils.ThreadRemoveFile;
import com.platform.utils.XmlOperationByDom4j;

import dk.brics.automaton.RegExp;

@Service(value = "scriptMakeService")
public class ScriptMakeService implements IScriptMakeService {

	@SuppressWarnings("static-access")
	public static Logger log = Configs.DAILY_ROLLING_LOGGER
			.getLogger(ScriptMakeService.class);

	@Resource(name = "preDataInfoDao")
	private PreDataInfoDao preDataInfoDao;

	@Override
	public int makeCfg() throws Exception {
		log.info("makeCfg");
		List<PreDataInfo> systemInfoList = preDataInfoDao.findAll();
		String path = FileOperateHelper
				.addLastSeparator(Configs.SQL_SCRIPT_PATH_STANDARD);
		StringBuffer sb = new StringBuffer();
		sb.append("市\t县（市、区）\t行政区划代码\r\n");
		Map<String, Object> startData = new HashMap<String, Object>();
		for (PreDataInfo preDataInfo : systemInfoList) {
			startData.put(preDataInfo.getAreaCode(), preDataInfo);

		}
		// 以地区为准--一个地区一个xml
		for (String key : startData.keySet()) {
			PreDataInfo preDataInfo = (PreDataInfo) startData.get(key);
			sb.append(preDataInfo.getCityName());
			sb.append("\t");
			sb.append(preDataInfo.getDistrictName());
			sb.append("\t");
			sb.append(preDataInfo.getAreaCode());
			sb.append("\r\n");
		}
		FileOperateHelper.fileReWrite(path + Constant.cfgFileName,
				sb.toString());
		log.info("makeCfg--end");
		return 1;
	}

	@Override
	public int makeXml() throws Exception {
		log.info("makeXml");
		List<PreDataInfo> systemInfoList = preDataInfoDao.findAll();
		String dirpath = FileOperateHelper
				.addLastSeparator(Configs.SQL_SCRIPT_PATH_STANDARD);
		Map<String, List<Object>> map = new HashMap<String, List<Object>>();
		for (PreDataInfo preDataInfo : systemInfoList) {
			putSystemByAreaCode(map, preDataInfo.getAreaCode(), preDataInfo);
		}
		// 一个地区一个xml
		for (String key : map.keySet()) {
			String areaPath = dirpath + key;
			File f = new File(areaPath);
			f.mkdir();
			List<Object> defList = new ArrayList<Object>();
			List<Object> list = map.get(key);
			for (Object object : list) {
				DefaultDataDescription defaul = new DefaultDataDescription();
				defaul.setvalue((PreDataInfo) object);
				defList.add(defaul);
			}

			XmlOperationByDom4j
					.createXml(FileOperateHelper.addLastSeparator(areaPath)
							+ key + ".xml", defList, "Data_info", "workRange");
		}
		log.info("makeXml--end");
		return 1;
	}

	@Override
	public List<MyFilesEntity> FindAllFiles() throws Exception {
		List<PreDataInfo> systemDataInfo = preDataInfoDao.findAll();
		// 查找 Configs.SQL_SCRIPT_PATH_LAST 路径下的 所有的文件：路径
		Map<String, String> sqlFilePathsLast = new HashMap<String, String>();
		sqlFilePathsLast = getAllFile(sqlFilePathsLast,
				Configs.SQL_SCRIPT_PATH_LAST);
		// 遍历 查找 Configs.SQL_SCRIPT_PATH_STANDARD 脚本文件 放入集合中
		Map<String, String> sqlFilePathsStandard = new HashMap<String, String>();
		sqlFilePathsStandard = getAllFile(sqlFilePathsStandard,
				Configs.SQL_SCRIPT_PATH_STANDARD);
		// 填充 脚本状态、位置的信息
		List<MyFilesEntity> result = setScript(systemDataInfo,
				sqlFilePathsStandard, sqlFilePathsLast);
		return result;
	}

	@Override
	public Map<String, Object> readSql(String name, MyFilesEntity form) {
		Map<String, Object> map = new HashMap<String, Object>();
		String path1 = "";
		String path2 = "";
		switch (name) {
			case "userTableStatus":
				path1 = form.getUserTableScriptPathStandard();
				map.put("data1Path", path1);
				map.put("data1", fileReader(path1));
				path2 = form.getUserTableScriptPathLast();
				map.put("data2Path", path2);
				map.put("data2", fileReader(path2));
				break;
			case "ckIndicateStatus":
				path1 = form.getCkIndicateScriptPathStandard();
				map.put("data1Path", path1);
				map.put("data1", fileReader(path1));
				path2 = form.getCkIndicateScriptPathLast();
				map.put("data2Path", path2);
				map.put("data2", fileReader(path2));
				break;
			case "ckPayStatus":
				path1 = form.getCkPayScriptPathStandard();
				map.put("data1Path", path1);
				map.put("data1", fileReader(path1));
				path2 = form.getCkPayScriptPathLast();
				map.put("data2Path", path2);
				map.put("data2", fileReader(path2));
				break;
			default:
				break;
		}
		return map;
	}

	@Override
	public int moveFiles(List<MyFilesEntity> files) throws Exception {

		return 0;
	}

	@Override
	public Map<String, Object> handleSqlFile(String type, String opt, String content, MyFilesEntity form) {
		Map<String, Object> map = new HashMap<String, Object>();
		String standardPath = "";
		String lastPath = "";
		if (null == form.getAreaCode() || form.getSysCode() < 1) {
			map.put("err", "请选择信息系统！");
			return map;
		}
//		选择哪种类型的 脚本  path 可能 = null
		switch (type) {
			case "userTableStatus":
				standardPath = form.getUserTableScriptPathStandard();
				if (null == standardPath || standardPath.isEmpty()) {
					standardPath = FileOperateHelper.addLastSeparator(Configs.SQL_SCRIPT_PATH_STANDARD) + form.getAreaCode()
							+ File.separator + "UserTablespace_" + form.getAreaCode() + "_" + form.getSysCode() + ".sql";
				}
				lastPath = form.getUserTableScriptPathLast();
				break;
			case "ckIndicateStatus":
				if (null == standardPath || standardPath.isEmpty()) {
					standardPath = FileOperateHelper.addLastSeparator(Configs.SQL_SCRIPT_PATH_STANDARD) + form.getAreaCode()
							+ File.separator + "Checkout_Indicate_" + form.getAreaCode() + "_" + form.getSysCode() + ".sql";
				}
				standardPath = form.getCkIndicateScriptPathStandard();
				lastPath = form.getCkIndicateScriptPathLast();
				break;
			case "ckPayStatus":
				if (null == standardPath || standardPath.isEmpty()) {
					standardPath = FileOperateHelper.addLastSeparator(Configs.SQL_SCRIPT_PATH_STANDARD) + form.getAreaCode()
							+ File.separator + "Checkout_Pay_" + form.getAreaCode() + "_" + form.getSysCode() + ".sql";
				}
				standardPath = form.getCkPayScriptPathStandard();
				lastPath = form.getCkPayScriptPathLast();
				break;
			default:
				map.put("err", "请选择脚本类型！");
				break;
		}
		if (map.containsKey("err_opt")) {
			return map;
		}
		switch (opt) {
			// 删除 最新的 脚本  （审核-保留）
			case "delete":  
				fileDelete(lastPath);
				break;
				// 最新脚本 替换 标准脚本（即 以最新脚本为准 ）(归档或审核-替换)
			case "replace":
				FileOperateHelper.fileReWrite(standardPath, fileReader(lastPath));
				fileDelete(lastPath);
				break;
				//新增 标准的脚本（注意 造出 对应的 standardPath standardPath不能 = null ''）（上传）
			case "add":
				FileOperateHelper.fileReWrite(standardPath,content);
				break;
				// （查看）
			case "read":  
				map = readSql(type, form);
				break;
			default:
				map.put("err", "请选择操作选项！");
				break;
		}
		return map;
	}

	/**
	 * @param map
	 * @param code
	 * @param data
	 * @return
	 */
	private Map<String, List<Object>> putSystemByAreaCode(
			Map<String, List<Object>> map, String code, PreDataInfo data) {
		List<Object> list = map.get(code);
		if (null == list) {
			list = new ArrayList<Object>();
		}
		list.add(data);
		map.put(code, list);
		return map;
	}

	/**
	 * 遍历文件
	 * 
	 * @param ps
	 * @param path
	 * @return
	 */
	public Map<String, String> getAllFile(Map<String, String> ps, String path) {
		File f = new File(path);
		String name = f.getName();
		// 如果是 sql文件
		if (name.endsWith(".sql") || name.endsWith(".SQL"))
			ps.put(name.toLowerCase(), f.getAbsolutePath());
		if (f.exists()) {
			String[] subpaths = f.list();
			if (null != subpaths) {
				for (String tmppath : subpaths) {
					getAllFile(ps, f.getAbsolutePath() + "/" + tmppath);
				}
			}
		}
		return ps;
	}

	/**
	 * @param systemDataInfo
	 *            系统信息
	 * @param sqlFilePathsStandard
	 *            标准的-归档的脚本
	 * @param sqlFilePathsLast
	 *            最新的脚本
	 * @return
	 */
	private List<MyFilesEntity> setScript(List<PreDataInfo> systemDataInfo,
			Map<String, String> sqlFilePathsStandard,
			Map<String, String> sqlFilePathsLast) {
		List<MyFilesEntity> fileEntitys = new ArrayList<MyFilesEntity>();
		for (PreDataInfo preDataInfo : systemDataInfo) {
			MyFilesEntity myfile = new MyFilesEntity();
			// 复制
			BeanCopy.copyBean(preDataInfo, myfile);
			// 归档表空间脚本的位置-
			String TablePathStandard = getFilePath("UserTablespace_",
					sqlFilePathsStandard, myfile, ".sql");
			myfile.setUserTableScriptPathStandard(TablePathStandard);
			// 归档预算 脚本的位置-
			String indicatePathStandard = getFilePath("Checkout_Indicate_",
					sqlFilePathsStandard, myfile, ".sql");
			myfile.setCkIndicateScriptPathStandard(indicatePathStandard);
			// 归档表空间脚本的位置-
			String payPathStandard = getFilePath("Checkout_Pay_",
					sqlFilePathsStandard, myfile, ".sql");
			myfile.setCkPayScriptPathStandard(payPathStandard);
			// 最新表空间脚本的位置-
			String TablePathLast = getFilePath("UserTablespace_",
					sqlFilePathsLast, myfile, ".sql");
			myfile.setUserTableScriptPathLast(TablePathLast);
			// 最新预算 脚本的位置-
			String indicatePathLast = getFilePath("Checkout_Indicate_",
					sqlFilePathsLast, myfile, ".sql");
			myfile.setCkIndicateScriptPathLast(indicatePathLast);
			// 最新表空间脚本的位置-
			String payPathLast = getFilePath("Checkout_Pay_", sqlFilePathsLast,
					myfile, ".sql");
			myfile.setCkPayScriptPathLast(payPathLast);
			// 设置 状态
			if ("ORACLE".equals(myfile.getDataBaseType().toUpperCase())) {
				myfile.setUserTableStatus(getStatus(
						myfile.getUserTableScriptPathStandard(),
						myfile.getUserTableScriptPathLast()));
			} else {
				myfile.setUserTableStatus(4);
			}
			myfile.setCkIndicateStatus(getStatus(
					myfile.getCkIndicateScriptPathStandard(),
					myfile.getCkIndicateScriptPathLast()));
			myfile.setCkPayStatus(getStatus(
					myfile.getCkPayScriptPathStandard(),
					myfile.getCkPayScriptPathLast()));
			myfile.setSysStatus(getTotalStatus(myfile));
			fileEntitys.add(myfile);
		}
		Compare4MyFilesEntity com = new Compare4MyFilesEntity();
		Collections.sort(fileEntitys, com);
		return fileEntitys;
	}

	/**
	 * 查找文件
	 * 
	 * @param prefix
	 * @param map
	 * @param myf
	 * @param affix
	 * @return
	 */
	private String getFilePath(String prefix, Map<String, String> map,
			MyFilesEntity myf, String affix) {
		StringBuffer sb = new StringBuffer();
		sb.append(prefix).append(myf.getAreaCode()).append("_")
				.append(myf.getSysCode()).append(affix);
		String fileName = sb.toString().toLowerCase();
		if (!map.containsKey(fileName)) {
			return null;
		}
		// 地区字母 小写 -- 文件属性小写
		String pathStandard = map.get(fileName);
		return pathStandard;
	}

	/**
	 * 返回状态--0： standard, last为空； 1：standard不空，last为空；
	 * 2：standard为空，last不空，3：standard不空，last不空 对应 含义，操作： 0：（有缺失，上传） ； 1： （正常
	 * ，查看）； 2：（待归档，归档） ； 3： （待审核，审核）
	 * 
	 * @param standard
	 * @param last
	 * @return
	 */
	private int getStatus(String standard, String last) {
		int status = 0;
		if (null != standard && !standard.isEmpty()) {
			status = status | 1;
		}
		if (null != last && !last.isEmpty()) {
			status = status | 2;
		}
		return status;
	}

	/**
	 * 返回状态 对应 含义，操作： 0：（有缺失，上传） ； 1： （正常 ，查看）； 2：（待归档，归档） ； 3： （待审核，审核）
	 * 
	 * @param standard
	 * @param last
	 * @return
	 */
	private int getTotalStatus(MyFilesEntity myfile) {
		Integer[] numArr = new Integer[3];
		Integer result = 1;
		numArr[0] = myfile.getUserTableStatus();
		numArr[1] = myfile.getCkIndicateStatus();
		numArr[2] = myfile.getCkPayStatus();
		for (Integer integer : numArr) {
			if (integer != 1) {
				result = integer;
			}
		}
		if (result == 1) {
			return result;
		}
		for (Integer integer : numArr) {
			if (integer != 1) {
				result = result & integer;
			}
		}
		return result;
	}

	private static String fileReader(String path) {
		StringBuffer sb = new StringBuffer();
		String tempString = "";
		if (null == path || "".equals(path)) {
			return sb.toString();
		}
		try {
			File file = new File(path);
			if (!file.exists())
				return null;
			FileInputStream fis = new FileInputStream(file);
			@SuppressWarnings("resource")
			BufferedReader br = new BufferedReader(new InputStreamReader(fis,
					"UTF-8"));
			while ((tempString = br.readLine()) != null) {
				sb.append(tempString).append("\r\n");
			}
		} catch (Exception e) {
			log.error(e.getStackTrace());
		}
		return sb.toString();
	}

	private static int fileDelete(String path) {
		if (null == path || "".equals(path)) {
			return -1;
		}
		File file = new File(path);
		if (!file.exists())
			return -1;
		if (!file.delete()) {
			ArrayList<String> arr = new ArrayList<String>();
			arr.add(path);
			new ThreadRemoveFile(arr).start();
		}
		return 1;
	}
}
