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

import com.fasterxml.jackson.databind.JsonNode;
import com.yihu.hos.core.datatype.StringUtil;
import com.yihu.hos.standard.model.standard.StdCDAModel;
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 01-9月-2015 17:17:50
 */
@Transactional
@Service("StdCDAService")
public class StdCDAService extends SQLGeneralDAO {

    public static final String BEAN_ID = "StdCDAService";

    public StdCDAService() {
    }

    public List<StdCDAModel> 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.StandardCDAGetListFailed);
    }

    public Object add(String stdVersion, String cda) {
        if (stdVersion.equals("{stdVersion}")) {
            throw new ApiException(ErrorCode.StandardCDAMissVersion);
        }

        try {
            StandardVersion standardVersion = new StandardVersion(stdVersion);
            StdCDAModel stdCdaModel = objectMapper.readValue(cda, StdCDAModel.class);
            this.add(standardVersion, stdCdaModel);

            return stdCdaModel.getId();
        } catch (IOException e) {
            e.printStackTrace();
        }

        throw new ApiException(ErrorCode.StandardCDASaveFailed);
    }

    public void delete(String stdVersion, Integer cdaId) {
        if (StringUtil.isEmpty(stdVersion)) {
            throw new ApiException(ErrorCode.StandardCDAMissVersion);
        }
        try {
            if (cdaId != null) {
                StandardVersion standardVersion = new StandardVersion(stdVersion);
                Session session = getCurrentSession();
                String sql = "delete from " + standardVersion.getCDATableName() + " where id = :id";
                Query query = session.createSQLQuery(sql);
                query.setInteger("id", cdaId);
                query.executeUpdate();
            }
        } catch (Exception e) {
            throw new ApiException(ErrorCode.StandardCDADeleteFailed);
        }
    }

    public Object update(String stdVersion, String cda) {
        if (stdVersion.equals("{stdVersion}")) {
            throw new ApiException(ErrorCode.StandardCDAMissVersion);
        }

        try {
            StandardVersion standardVersion = new StandardVersion(stdVersion);
            StdCDAModel stdCdaModel = objectMapper.readValue(cda, StdCDAModel.class);
            this.modify(standardVersion, stdCdaModel);
            return stdCdaModel;
        } catch (IOException e) {
            e.printStackTrace();
        }

        throw new ApiException(ErrorCode.StandardCDAUpdateFailed);
    }

    public StdCDAModel get(String stdVersion, Integer cdaId) {
        if (stdVersion.equals("{stdVersion}")) {
            throw new ApiException(ErrorCode.StandardCDAMissVersion);
        }

        try {
            StandardVersion standardVersion = new StandardVersion(stdVersion);
            return this.get(standardVersion, cdaId);
        } catch (Exception e) {

        }

        throw new ApiException(ErrorCode.StandardCDAGetFailed);
    }

    private StdCDAModel get(StandardVersion standardVersion, Integer cdaId) {
        Session session = getCurrentSession();
        String cdaTableName = standardVersion.getCDATableName();

        String sql = "select id, std_id, code, name, path, description, catalog_id from " + cdaTableName + " where id = :id";
        Query query = session.createSQLQuery(sql);
        query.setInteger("id", cdaId);
        query.setResultTransformer(new BeanTransformer<>(StdCDAModel.class));
        return (StdCDAModel) query.uniqueResult();
    }

    private void modify(StandardVersion standardVersion, StdCDAModel stdCdaModel) throws IOException {
        String cdaTableName = standardVersion.getCDATableName();

        JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(stdCdaModel));
        SqlCreator sqlCreator = new SqlCreator(StdCDAModel.class);
        String sql = sqlCreator.updateDataByTableKey(cdaTableName, jsonNode);
        Query query = getExeuteQuery(sqlCreator, sql);
        query.executeUpdate();
    }

    private void add(StandardVersion standardVersion, StdCDAModel stdCdaModel) throws IOException {
        String cdaTableName = standardVersion.getCDATableName();
        Session session = getCurrentSession();
        String sql = "select max(id) from " + cdaTableName;
        Query query = session.createSQLQuery(sql);
        Object object = query.uniqueResult();
        stdCdaModel.setId(object == null ? 1 : Integer.parseInt(object.toString()) + 1);

        JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(stdCdaModel));
        SqlCreator sqlCreator = new SqlCreator(StdCDAModel.class);
        sql = sqlCreator.insertData(cdaTableName, jsonNode);
        query = getExeuteQuery(sqlCreator, sql);
        query.executeUpdate();
    }

    private List<StdCDAModel> getList(StandardVersion standardVersion, Map<String, Object> query,  Map<String, String> order, Integer limit, Integer offset) {
        SqlCreator sqlCreator = new SqlCreator(StdCDAModel.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.getCDATableName());
        Query sessionQuery = getQuery(sqlCreator, sql);
        if (limit != null) {
            sessionQuery.setMaxResults(limit);
            if (offset != null) {
                sessionQuery.setFirstResult((offset - 1) * limit);
            }
        }
        return (List<StdCDAModel>) sessionQuery.list();

    }

}//end CDADocumentManager