package cn.tsy.idsse.dsds.service.sample;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.hme.data.model.frame.optr.FrameOptr;
import cn.hme.framework.helper.date.LocalDateHelper;
import cn.hme.framework.helper.date.LocalDateHelper.LocalDateCompareType;
import cn.hme.framework.helper.lang.StringHelper;
import cn.hme.framework.jdbc.provider.builder.SqlBuilder;
import cn.hme.framework.jdbc.provider.builder.SqlCondition;
import cn.hme.framework.jdbc.provider.builder.SqlQuery;
import cn.hme.framework.jdbc.provider.page.OrderBy;
import cn.hme.framework.web.exception.BusinessException;
import cn.hme.framework.web.helper.FrameAssertHelper;
import cn.tsy.data.idsse.dsds.mapper.dict.DictDataMapper;
import cn.tsy.data.idsse.dsds.mapper.dict.DictEquipmentMapper;
import cn.tsy.data.idsse.dsds.mapper.dict.DictPlatformMapper;
import cn.tsy.data.idsse.dsds.mapper.sample.SampleDatasetMapper;
import cn.tsy.data.idsse.dsds.mapper.sample.SampleDatasetTrackMapper;
import cn.tsy.data.idsse.dsds.mapper.sample.SampleLineMapper;
import cn.tsy.data.idsse.dsds.mapper.sample.SampleStationMapper;
import cn.tsy.data.idsse.dsds.mapper.voyage.VoyageMemberMapper;
import cn.tsy.data.idsse.dsds.mapper.voyage.VoyageRegMapper;
import cn.tsy.data.idsse.dsds.model.dict.DictData;
import cn.tsy.data.idsse.dsds.model.dict.DictEquipment;
import cn.tsy.data.idsse.dsds.model.dict.DictPlatform;
import cn.tsy.data.idsse.dsds.model.sample.SampleDataset;
import cn.tsy.data.idsse.dsds.model.sample.SampleDatasetTrack;
import cn.tsy.data.idsse.dsds.model.sample.SampleLine;
import cn.tsy.data.idsse.dsds.model.sample.SampleStation;
import cn.tsy.data.idsse.dsds.model.voyage.VoyageMember;
import cn.tsy.data.idsse.dsds.model.voyage.VoyageReg;
import cn.tsy.idsse.dsds.constant.VoyageJobType;

@Service
public class SampleDatasetService {
	@Autowired
	private VoyageRegMapper mVoyage;
	@Autowired
	private SampleDatasetMapper mDataset;
	@Autowired
	private SampleLineMapper mLine;
	@Autowired
	private SampleStationMapper mStation;
	@Autowired
	private SampleDatasetTrackMapper mMapper;
	@Autowired
	private DictPlatformMapper mPlatform;
	@Autowired
	private DictEquipmentMapper mEquipment;
	@Autowired
	private DictDataMapper mData;
	@Autowired
	private VoyageMemberMapper mMember;

	/***********************
	 * 增加或者修改
	 * 
	 */
	public SampleDataset editDataset(SampleDataset dataset, Integer old_dataset_id, FrameOptr optr) {
		FrameAssertHelper.isNotNull(dataset.getVoyage_id(), "航次号不能为空！");
		FrameAssertHelper.isNotNull(dataset.getPlatform_id(), "平台类型不能为空！");
		// FrameAssertHelper.isNotEmpty(dataset.getPlatform_name(), "平台名称不能为空！");
		FrameAssertHelper.isNotNull(dataset.getEquipment_id(), "设备类型不能为空！");
		FrameAssertHelper.isNotNull(dataset.getData_id(), "数据样品类型不能为空！");
		FrameAssertHelper.isNotEmpty(dataset.getJob_type(), "作业类型不能为空！");
		// TS2-37-1_SY665_JXS_WW_
		// 数据样品编号： 航次号_潜次号_设备类型_数据样品类型_作业序号
		//
		VoyageReg voyage = this.mVoyage.find(dataset.getVoyage_id());
		FrameAssertHelper.isNotNull(voyage, "未找到指定的航次信息，请检查！");

		if (dataset.getWater_in_time() != null && dataset.getWater_out_time() != null) {
			dataset.setWater_minutes(LocalDateHelper.calTimeDiff(dataset.getWater_out_time(), dataset.getWater_in_time(), LocalDateCompareType.Minute).intValue());
		}
		if (dataset.getBottom_time() != null && dataset.getReceive_time() != null) {
			dataset.setJob_minutes(LocalDateHelper.calTimeDiff(dataset.getReceive_time(), dataset.getBottom_time(), LocalDateCompareType.Minute).intValue());
		}
		if (dataset.getTsy_id() == null) {
			DictPlatform platform = this.mPlatform.find(dataset.getPlatform_id());
			DictEquipment equipment = this.mEquipment.find(dataset.getEquipment_id());
			DictData data = this.mData.find(dataset.getData_id());
			dataset.setCreate_time(LocalDateTime.now());
			dataset.setPlatform_type(platform.getPlatform_name());
			dataset.setPlatform_alias(platform.getPlatform_alias());
			dataset.setEquipment_type(equipment.getEquipment_name());
			dataset.setEquipment_alias(equipment.getEquipment_alias());
			dataset.setData_alias(data.getData_alias());
			dataset.setData_type(data.getData_name());
			dataset.setVoyage_name(voyage.getVoyage_name());
			// 新增，需要生成数据集和数据样品编号
			String dataset_name = voyage.getVoyage_name() + "_" + (StringHelper.isEmpty(dataset.getDiving_sn()) ? dataset.getPlatform_alias() : dataset.getDiving_sn()) + "_" + dataset.getEquipment_alias() + "_" + dataset.getData_alias();
			// 找到序号
			SampleDataset ds = this.mDataset.findWithColumn("dataset_name", dataset_name);
			if (ds != null) {
				return ds;
				// throw new BusinessException("数据集["++"]已经存在，无需重复添加！");
			}

			dataset.setDataset_name(dataset_name);
			this.mDataset.insert(dataset);

			if (old_dataset_id != null && StringHelper.hasValue(dataset.getDiving_sn())) {
				// 如果是从旧数据集复制的
				SampleDataset old = this.mDataset.find(old_dataset_id);
				if (StringHelper.hasValue(old.getDiving_track_file())) {
					// 如果有潜轨迹文件
					SampleDataset dd = new SampleDataset();
					dd.setTsy_id(dataset.getTsy_id());
					dd.setDiving_track_file(old.getDiving_track_file());
					this.mDataset.update(dd);
					// 轨迹
					for (SampleDatasetTrack t : this.mMapper.selectListByColumnAndSimpleOrder("dataset_id", old_dataset_id, OrderBy.of("tsy_id"))) {
						t.setDataset_id(dataset.getTsy_id());
						t.setTsy_id(null);
						this.mMapper.insert(t);
					}
				}

			}

		} else {
			this.mDataset.update(dataset);

		}
		return dataset;

	}

	public List<SampleDataset> uploadSample(List<List<String>> values, FrameOptr optr) {
		/****
		 * *航次名称 *平台类型 *平台名称 *潜次序号 布放经度 布放纬度 布放深度
		 * 入水时间 出水时间 左舷 右舷 主驾
		 * 坐底时间 抛载时间 回收时间
		 * *设备类型 设备序列号
		 * *作业类型 *样品类型 序号 采样时间 经度 纬度 深度 测线号 深度 开始经度 开始纬度 结束经度 结束纬度 开始时间 结束时间 备注 数据公开期限
		 */

		FrameAssertHelper.hasValue(values, "导入的文件中无有效数据，请检查！");
		for (int i = 1; i < values.size(); i++) {
			List<String> list = values.get(i);
			if (list.get(0) == null || list.get(0).trim().length() == 0)
				break;
			// *航次名称 *平台类型 *平台名称 *潜次序号 布放经度 布放纬度 布放深度
			// 入水时间 出水时间 左舷 右舷 主驾 坐底时间 抛载时间 回收时间
			// *设备类型 设备序列号 *作业类型 *样品类型 文物器号
			String voyage_name = list.get(0);
			String platform_type = list.get(1);
			String platform_name = list.get(2);
			String diving_name = list.get(3);
			String wiring_lon = list.get(4);
			String wiring_lat = list.get(5);
			String wiring_deep = list.get(6);
			String water_in_time = list.get(7);
			String water_out_time = list.get(8);
			String driver_left = list.get(9);
			String driver_right = list.get(10);
			String driver_master = list.get(11);
			String bottom_time = list.get(12);
			String throwing_time = list.get(13);
			String receive_time = list.get(14);
			String equipment_type = list.get(15);
			String equipment_sn = list.get(16);
			String job_type = list.get(17);
			String data_name = list.get(18);

			String station_seq = list.get(19);
			// 采样时间 经度 纬度 深度
			String sampling_time = list.get(20);
			String sampling_lon = list.get(21);
			String sampling_lat = list.get(22);
			String sampling_deep = list.get(23);
			// 测线号 深度 开始经度 开始纬度 结束经度 结束纬度 开始时间 结束时间 备注 数据公开期限
			String line_sn = list.get(24);
			String line_deep = list.get(25);
			String start_lon = list.get(26);
			String start_lat = list.get(27);
			String end_lon = list.get(28);
			String end_lat = list.get(29);
			String start_time = list.get(30);
			String end_time = list.get(31);
			String data_status = list.get(32);
			String remark = list.get(33);
			String data_role = list.get(34);
			String fouing_org = list.get(35);

			SampleDataset sa = new SampleDataset();
			VoyageReg voyage = this.mVoyage.findWithColumn("voyage_name", voyage_name);
			if (voyage == null)
				throwError(i, "航次[" + voyage_name + "]未找到，请先添加该航次");
			sa.setVoyage_id(voyage.getTsy_id());
			sa.setVoyage_name(voyage_name);
			DictPlatform platform = this.mPlatform.findWithColumn("platform_name", platform_type);
			if (platform == null)
				throwError(i, "平台类型[" + platform_type + "]未找到，请先添加该平台类型");
			sa.setPlatform_type(platform_type);
			sa.setPlatform_name(platform_name);
			sa.setPlatform_id(platform.getTsy_id());
			sa.setPlatform_alias(platform.getPlatform_alias());
			DictEquipment equipment = this.mEquipment.findWithColumn("equipment_name", equipment_type);
			if (equipment == null)
				throwError(i, "设备类型[" + equipment_type + "]未找到，请先添加该设备类型");
			sa.setEquipment_alias(equipment.getEquipment_alias());
			sa.setEquipment_id(equipment.getTsy_id());
			sa.setEquipment_type(equipment_type);
			DictData data = this.mData.findWithColumn("data_name", data_name);
			if (data == null)
				throwError(i, "数据样品类型[" + data_name + "]未找到，请先添加该数据样品类型");
			sa.setData_alias(data.getData_alias());
			sa.setData_id(data.getTsy_id());
			sa.setData_type(data.getData_name());
			sa.setJob_type(job_type);
			sa.setDiving_sn(diving_name);
			sa.setEquipment_sn(equipment_sn);

			if (StringHelper.hasValue(wiring_lon))
				sa.setWiring_lon(checkValue(wiring_lon));
			if (StringHelper.hasValue(wiring_lat))
				sa.setWiring_lat(checkValue(wiring_lat));
			if (StringHelper.hasValue(wiring_deep))
				sa.setWiring_deep(wiring_deep);
			if (StringHelper.hasValue(water_in_time))
				sa.setWater_in_time(LocalDateHelper.parseDateTime(water_in_time));
			if (StringHelper.hasValue(water_out_time))
				sa.setWater_out_time(LocalDateHelper.parseDateTime(water_out_time));
			if (StringHelper.hasValue(driver_left)) {
				sa.setDriver_left(driver_left);
				// 获取科学家单位
				List<VoyageMember> mArray = this.mMember.selectList(SqlBuilder.create().addSqlCondition(SqlCondition.of("voyage_id", voyage.getTsy_id()))
						.addSqlCondition(SqlCondition.of("member_name", driver_left)));
				if(mArray.size()>0)
					sa.setDriver_unit_left(mArray.get(0).getMember_unit());
			}
			if (StringHelper.hasValue(driver_right)) {
				sa.setDriver_right(driver_right);
				List<VoyageMember> mArray = this.mMember.selectList(SqlBuilder.create().addSqlCondition(SqlCondition.of("voyage_id", voyage.getTsy_id()))
						.addSqlCondition(SqlCondition.of("member_name", driver_right)));
				if(mArray.size()>0)
					sa.setDriver_unit_right(mArray.get(0).getMember_unit());
			}
			if (StringHelper.hasValue(driver_master))
				sa.setDriver_master(driver_master);
			if (StringHelper.hasValue(bottom_time))
				sa.setBottom_time(LocalDateHelper.parseDateTime(bottom_time));
			if (StringHelper.hasValue(throwing_time))
				sa.setThrowing_time(LocalDateHelper.parseDateTime(throwing_time));
			if (StringHelper.hasValue(receive_time))
				sa.setReceive_time(LocalDateHelper.parseDateTime(receive_time));

			// 新增，需要生成数据集和数据样品编号
			String dataset_name = voyage.getVoyage_name() + "_" + (StringHelper.isEmpty(diving_name) ? platform.getPlatform_alias() : diving_name) + "_" + equipment.getEquipment_alias() + "_" + data.getData_alias();
			sa.setDataset_name(dataset_name);
			if (sa.getWater_in_time() != null && sa.getWater_out_time() != null) {
				sa.setWater_minutes(LocalDateHelper.calTimeDiff(sa.getWater_out_time(), sa.getWater_in_time(), LocalDateCompareType.Minute).intValue());
			}
			if (sa.getBottom_time() != null && sa.getThrowing_time() != null) {
				sa.setJob_minutes(LocalDateHelper.calTimeDiff(sa.getThrowing_time(), sa.getBottom_time(), LocalDateCompareType.Minute).intValue());
			}
			SampleDataset ds = this.mDataset.findWithColumn("dataset_name", dataset_name);
			if (ds == null) {
				sa.setCreate_time(LocalDateTime.now());
				this.mDataset.insert(sa);
			} else {
				sa.setTsy_id(ds.getTsy_id());
				this.mDataset.update(sa);
			}

			SampleLine line = new SampleLine();
			SampleStation st = new SampleStation();
			if (StringHelper.isEmpty(job_type))
				throwError(i, "作业类型为空，请检查！");
			if (VoyageJobType.Line.equals(job_type)) {
				if(StringHelper.hasValue(fouing_org))
					line.setFunding_org(fouing_org);
				if (StringHelper.hasValue(line_sn))
					line.setLine_sn(line_sn);
				if (StringHelper.hasValue(start_lon))
					line.setStart_lon(checkValue(start_lon));
				if (StringHelper.hasValue(start_lat))
					line.setStart_lat(checkValue(start_lat));
				if (StringHelper.hasValue(end_lon))
					line.setEnd_lon(checkValue(end_lon));
				if (StringHelper.hasValue(end_lat))
					line.setEnd_lat(checkValue(end_lat));
				if (StringHelper.hasValue(start_time))
					line.setStart_time(LocalDateHelper.parseDateTime(start_time));
				if (StringHelper.hasValue(end_time))
					line.setEnd_time(LocalDateHelper.parseDateTime(end_time));
				if(StringHelper.hasValue(data_status))
					line.setSample_status(data_status);
				line.setDataset_name(dataset_name);
				line.setDataset_id(sa.getTsy_id());
				if (StringHelper.isEmpty(line_sn)) {
					// 找到序号
					Integer total = this.mLine.selectCount(SqlQuery.create().eq("dataset_name", dataset_name));
					String sample_code = "";
					int seq = 1;
					if (total == null || total - 0 == 0)
						sample_code = dataset_name + "_01";
					else {
						seq = total + 1;
						sample_code = dataset_name + StringHelper.leftPadding(seq + "", 2, '0');
					}
					line.setSample_seq(StringHelper.leftPadding(seq + "", 2, '0'));
					line.setSample_name(sample_code);
				} else {
					line.setLine_sn(StringHelper.leftPadding(line_sn + "", 2, '0'));
					line.setSample_seq(StringHelper.leftPadding(line_sn + "", 2, '0'));
					line.setSample_name(dataset_name + "_" + StringHelper.leftPadding(line_sn + "", 2, '0'));
				}
				if (StringHelper.hasValue(line_deep))
					line.setLine_deep(line_deep);
				if (StringHelper.hasValue(remark))
					line.setSample_remark(remark);
				if (StringHelper.hasValue(data_role))
					line.setPublish_rule(data_role);

				line.setCreate_time(LocalDateTime.now());
				// 判断是否存在
				if (this.mLine.findWithColumn("sample_name", line.getSample_name()) != null) {
					this.mLine.deleteByColumn("sample_name", line.getSample_name());
					// throwError(i, "测线作业[" + st.getSample_name() + "]已经存在！");
				}
				this.mLine.insert(line);
			} else if (VoyageJobType.Station.equals(job_type)) {
				if(StringHelper.hasValue(fouing_org))
					st.setFunding_org(fouing_org);
				if (StringHelper.hasValue(sampling_time))
					st.setSampling_time(LocalDateHelper.parseDateTime(sampling_time));
				if (StringHelper.hasValue(sampling_lat))
					st.setSampling_lat(checkValue(sampling_lat));
				if (StringHelper.hasValue(sampling_lon))
					st.setSampling_lon(checkValue(sampling_lon));
				if (StringHelper.hasValue(sampling_deep))
					st.setSampling_deep(sampling_deep);
				if (StringHelper.isEmpty(station_seq)) {
					// 找到序号
					Integer total = this.mStation.selectCount(SqlQuery.create().eq("dataset_name", dataset_name));
					String sample_code = "";
					int seq = 1;
					if (total == null || total - 0 == 0)
						sample_code = dataset_name + "_01";
					else {
						seq = total + 1;
						sample_code = dataset_name + StringHelper.leftPadding(seq + "", 2, '0');
					}
					st.setSample_seq(StringHelper.leftPadding(seq + "", 2, '0'));
					st.setSample_name(sample_code);
				} else {
					st.setSample_seq(StringHelper.leftPadding(station_seq + "", 2, '0'));
					st.setSample_name(dataset_name + "_" + StringHelper.leftPadding(station_seq + "", 2, '0'));
				}

				if (StringHelper.hasValue(remark))
					st.setSample_remark(remark);
				if (StringHelper.hasValue(data_role))
					st.setPublish_rule(data_role);
				// 判断是否存在
				if (this.mStation.findWithColumn("sample_name", st.getSample_name()) != null) {
					// throwError(i, "站位作业[" + st.getSample_name() + "]已经存在！");
					this.mStation.deleteByColumn("sample_name", st.getSample_name());
				}
				st.setCreate_time(LocalDateTime.now());
				st.setDataset_name(dataset_name);
				st.setDataset_id(sa.getTsy_id());
				this.mStation.insert(st);

			} else
				throwError(i, "作业类型[" + job_type + "]必须为测线作业或者站位作业！");

		}
		return new ArrayList<>();
	}

	/****************
	 * 删除数据样品
	 * 
	 */
	public void deleteDataset(int dataset_id) {
		/****************
		 * @todo 判断是否能实际删除
		 */
		this.mDataset.deleteByKey(dataset_id);
	}

	public void throwError(int row, String msg) {
		throw new BusinessException("数据样品信息导入失败->第[" + (row + 1) + "]行:" + msg);

	}

	// 经纬度保留4位
	public String checkValue(String value) {
		try {
			return String.format("%.4f", Double.parseDouble(value));
		} catch (Exception e) {
			return value;
		}
	}

}
