package com.yihu.hos.standard.service.standard;


import com.yihu.hos.core.datatype.StringUtil;
import com.yihu.hos.standard.model.standard.StdCDADatasetModel;
import com.yihu.hos.standard.service.bo.StandardVersion;
import com.yihu.hos.web.framework.constant.ErrorCode;
import com.yihu.hos.web.framework.dao.SQLGeneralDAO;
import com.yihu.hos.web.framework.exception.ApiException;
import com.yihu.hos.web.framework.util.sql.BeanTransformer;
import com.yihu.hos.web.framework.util.sql.RequestParamTransformer;
import com.yihu.hos.web.framework.util.sql.SqlCreator;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * @author AndyCai
 * @version 1.0
 * @created 02-9月-2015 14:00:55
 */
@Transactional
@Service("StdCDADatasetService")
public class StdCDADatasetService extends SQLGeneralDAO {

    public static final String BEAN_ID = "StdCDADatasetService";

    public StdCDADatasetService() {

    }

    public void finalize() throws Throwable {

    }

    public List<StdCDADatasetModel> getList(String stdVersion, String condition, String order, Integer limit, Integer offset) {
        try {
            Map queryMap = RequestParamTransformer.parseJsonToMap(condition);
            Map orderMap = RequestParamTransformer.parseJsonToMap(order);
            StandardVersion standardVersion = new StandardVersion(stdVersion);
            return this.getList(standardVersion, queryMap, orderMap, limit, offset);
        } catch (Exception e) {
            e.printStackTrace();
        }

        throw new ApiException(ErrorCode.StandardCDADatasetGetListFailed);
    }

    public StdCDADatasetModel add(String stdVersion, String cdaDataset) {
        if (stdVersion.equals("{stdVersion}")) {
            throw new ApiException(ErrorCode.StandardCDADatasetMissVersion);
        }
        try {
            StandardVersion standardVersion = new StandardVersion(stdVersion);
            StdCDADatasetModel stdCdaDatasetModel = objectMapper.readValue(cdaDataset, StdCDADatasetModel.class);
            this.add(standardVersion, stdCdaDatasetModel);

            return stdCdaDatasetModel;
        } catch (IOException e) {
            e.printStackTrace();
        }

        throw new ApiException(ErrorCode.StandardCDADatasetSaveFailed);
    }

    public void delete(String stdVersion, Integer cdadatasetId) {
        if (StringUtil.isEmpty(stdVersion)) {
            throw new ApiException(ErrorCode.StandardCDADatasetMissVersion);
        }

        if (cdadatasetId == null) {
            throw new ApiException(ErrorCode.StandardCDADatasetMissID);
        }

        try {
            if (cdadatasetId != null) {
                StandardVersion standardVersion = new StandardVersion(stdVersion);
                Session session = getCurrentSession();
                String sql = "delete from " + standardVersion.getCDADatasetTableName() + " where id = :id";
                Query query = session.createSQLQuery(sql);
                query.setInteger("id", cdadatasetId);
                query.executeUpdate();
            }
        } catch (Exception e) {
            throw new ApiException(ErrorCode.StandardCDADatasetDeleteFailed);
        }
    }

    public StdCDADatasetModel update(String stdVersion, String cdaDataset) {
        if (stdVersion.equals("{stdVersion}")) {
            throw new ApiException(ErrorCode.StandardCDADatasetMissVersion);
        }

        try {
            StandardVersion standardVersion = new StandardVersion(stdVersion);
            StdCDADatasetModel stdCdaDatasetModel = objectMapper.readValue(cdaDataset, StdCDADatasetModel.class);
            this.modify(standardVersion, stdCdaDatasetModel);

            return stdCdaDatasetModel;
        } catch (IOException e) {
            e.printStackTrace();
        }

        throw new ApiException(ErrorCode.StandardCDADatasetUpdateFailed);
    }

    public StdCDADatasetModel get(String stdVersion, Integer cdadatasetId) {
        if (StringUtil.isEmpty(stdVersion)) {
            throw new ApiException(ErrorCode.StandardCDADatasetMissVersion);
        }

        if (cdadatasetId == null) {
            throw new ApiException(ErrorCode.StandardCDADatasetMissID);
        }

        try {
            if (cdadatasetId != null) {
                StandardVersion standardVersion = new StandardVersion(stdVersion);
                Session session = getCurrentSession();
                String cdaDatasetTableName = standardVersion.getCDADatasetTableName();

                String sql = "select id, cda_id, dataset_id from " + cdaDatasetTableName + " where id = :id";
                Query query = session.createSQLQuery(sql);
                query.setInteger("id", cdadatasetId);
                query.setResultTransformer(new BeanTransformer<>(StdCDADatasetModel.class));
                return (StdCDADatasetModel) query.uniqueResult();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        throw new ApiException(ErrorCode.StandardCDADatasetGetFailed);
    }

    private void modify(StandardVersion standardVersion, StdCDADatasetModel stdCdaDatasetModel) {
        Session session = getCurrentSession();
        String cdaDatasetTableName = standardVersion.getCDADatasetTableName();

        String sql = "update " + cdaDatasetTableName +
                "set " +
                "id = :id, " +
                "cda_id = :cda_id, " +
                "dataset_id = :dataset_id " +
                "where id = :id";

        Query query = session.createSQLQuery(sql);
        query.setInteger("id", stdCdaDatasetModel.getId());
        query.setInteger("cda_id", stdCdaDatasetModel.getCdaID());
        query.setInteger("dataset_id", stdCdaDatasetModel.getdatasetId());
        query.executeUpdate();
    }

    private void add(StandardVersion standardVersion, StdCDADatasetModel stdCdaDatasetModel) {
        Session session = getCurrentSession();
        String cdaDatasetTableName = standardVersion.getCDADatasetTableName();

        String sql = "select max(id) from " + cdaDatasetTableName;
        Query query = session.createSQLQuery(sql);
        Object object = query.uniqueResult();
        stdCdaDatasetModel.setId(object == null ? 1 : Integer.parseInt(object.toString()) + 1);

        sql = "insert into " + cdaDatasetTableName + "(id, cda_id, dataset_id)"
                + "VALUES (:id, :cda_id, :dataset_id)";

        query = session.createSQLQuery(sql);
        query.setInteger("id", stdCdaDatasetModel.getId());
        query.setInteger("cda_id", stdCdaDatasetModel.getCdaID());
        query.setInteger("dataset_id", stdCdaDatasetModel.getdatasetId());

        query.executeUpdate();
    }

    private List<StdCDADatasetModel> getList(StandardVersion standardVersion, Map<String, Object> query, Map<String, String> order, Integer limit, Integer offset) {
        SqlCreator sqlCreator = new SqlCreator(StdCDADatasetModel.class);
        for (String key : query.keySet()) {
            sqlCreator.equalCondition(key, query.get(key));
        }
        for (String key : order.keySet()) {
            sqlCreator.order(key, order.get(key));
        }

        String sql = sqlCreator.selectData(standardVersion.getCDADatasetTableName());
        Query sessionQuery = getQuery(sqlCreator, sql);
        if (limit != null) {
            sessionQuery.setMaxResults(limit);
            if (offset != null) {
                sessionQuery.setFirstResult((offset - 1) * limit);
            }
        }

        return (List<StdCDADatasetModel>) sessionQuery.list();
    }

}//end CDADatasetRelationshipManager