/**
 * 用于管理kpi数据映射
 *
 * @author xiongjian
 */
@Repository("kpiSyncMappingStorage")
public class KpiSyncMappingStorage {

  private Log log = LogFactory.getLogger("DataSourceToCategoryStorage");
  @Autowired private KpiCateStorage kCateStorage;
  @Autowired private DataSourceStorage dsStorage;

  public List<KpiSyncMapping> getAll() throws Exception {
    String sql = "select * from KpiSyncMapping";
    return query(sql);
  }

  public KpiSyncMapping getByName(String name) throws Exception {
    List<KpiSyncMapping> list = getByProperty("name", name);
    if (list.size() == 1) {
      return list.get(0);
    } else if (list.size() > 1) {
      log.eLog("KPI同步映射[" + name + "]不唯一");
      throw new Exception("KPI同步映射[" + name + "]不唯一");
    } else {
      return null;
    }
  }

  public KpiSyncMapping getById(String id) throws Exception {
    List<KpiSyncMapping> list = getByProperty("_id", id);
    if (list.size() == 1) {
      return list.get(0);
    } else if (list.size() > 1) {
      log.eLog("KPI同步映射[" + id + "]不唯一");
      throw new Exception("KPI同步映射[" + id + "]不唯一");
    } else {
      return null;
    }
  }

  public List<KpiSyncMapping> getByProperty(String key, String val) throws Exception {
    String match = "select * from KpiSyncMapping where `" + key + "` = '" + val + "'";
    return query(match);
  }

  public void delById(String id) throws Exception {
    String del = "delete from KpiSyncMapping where _id = '" + id + "'";
    MongoConnect.executeUpdate(del);
  }

  public void delAll() throws Exception {
    String del = "delete from KpiSyncMapping";
    MongoConnect.executeUpdate(del);
  }

  public KpiSyncMapping save(KpiSyncMapping kpiMapping) throws Exception {
    try {
      Connection conn = MongoConnect.getConnection();
      PreparedStatement pstmt =
          conn.prepareStatement(
              "insert into KpiSyncMapping(name,cateId,dataSourceId,fieldMap,owner) values(?,?,?,?,?)");
      pstmt.setString(1, kpiMapping.getName() == null ? "" : kpiMapping.getName());
      pstmt.setString(2, kpiMapping.getCateId() == null ? "" : kpiMapping.getCateId());
      pstmt.setString(3, kpiMapping.getDataSourceId() == null ? "" : kpiMapping.getDataSourceId());
      pstmt.setString(
          4,
          kpiMapping.getFieldMap() == null
              ? "{}"
              : JSONObject.fromObject(kpiMapping.getFieldMap()).toString());
      pstmt.setString(5, kpiMapping.getOwner());
      pstmt.executeUpdate();
    } catch (Exception e) {
      throw e;
    }
    return getByName(kpiMapping.getName());
  }

  public KpiSyncMapping update(KpiSyncMapping kpiMapping) throws Exception {
    try {
      Connection conn = MongoConnect.getConnection();
      PreparedStatement pstmt =
          conn.prepareStatement(
              "update KpiSyncMapping set name=?,cateId=?,dataSourceId=?,fieldMap=? where _id=?");
      pstmt.setString(1, kpiMapping.getName() == null ? "" : kpiMapping.getName());
      pstmt.setString(2, kpiMapping.getCateId() == null ? "" : kpiMapping.getCateId());
      pstmt.setString(3, kpiMapping.getDataSourceId() == null ? "" : kpiMapping.getDataSourceId());
      pstmt.setString(
          4,
          kpiMapping.getFieldMap() == null
              ? "{}"
              : JSONObject.fromObject(kpiMapping.getFieldMap()).toString());
      pstmt.setString(5, kpiMapping.getId());
      pstmt.executeUpdate();
    } catch (Exception e) {
      throw e;
    }
    return kpiMapping;
  }

  public boolean existByName(String name) {
    try {
      if (getByName(name) == null) return false;
    } catch (Exception e) {
    }
    return true;
  }

  public boolean existById(String id) {
    try {
      if (getById(id) == null) return false;
    } catch (Exception e) {
    }
    return true;
  }

  public List<KpiSyncMapping> query(String sql) throws Exception {
    List<KpiSyncMapping> ret = new ArrayList<KpiSyncMapping>();
    try {
      Connection conn = MongoConnect.getConnection();
      Statement stmt = conn.createStatement();
      ResultSet rs = stmt.executeQuery(sql);
      while (rs.next()) {
        String id = rs.getString("_id");
        String name = rs.getString("name");
        String cateId = rs.getString("cateId");
        String dataSourceId = rs.getString("dataSourceId");
        JSONObject fieldMap = null;
        try {
          fieldMap = JSONObject.fromObject(rs.getString("fieldMap"));
        } catch (Exception e) {
          fieldMap = new JSONObject();
        }
        KpiCategory cate = kCateStorage.getById(cateId);
        DataSourcePool dataSource = dsStorage.getById(dataSourceId);
        @SuppressWarnings("unchecked")
        KpiSyncMapping ksm = new KpiSyncMapping(name, cate, dataSource, dataSourceId, fieldMap);
        ksm.setId(id);
        ksm.setOwner(rs.getString("owner"));
        ret.add(ksm);
      }
    } catch (Exception e) {
      throw e;
    }
    return ret;
  }
}
// @Component("PerfDataCleanupTask")
public class PerfDataCleanupTask {
  private Log log = LogFactory.getLogger("PerfDataCleanupTask");
  /** 每4小时清理一下4小时之前的数据。 */
  private int interval = 14400;

  /** 数据源。 */
  @Resource(name = "eventDS")
  private DataSource ds;

  private String cleanSql = "delete from MON_PERF_DATA where  METRIC_TIME < ?";

  private boolean isStart;

  Thread cleanupThread;

  /** */
  public PerfDataCleanupTask() {
    isStart = false;
  }

  public void start() {
    isStart = true;
    Thread cleanupThread =
        new Thread() {
          @Override
          public void run() {
            while (isStart) {
              cleanupData();

              try {
                // 等待指定时间
                Thread.sleep(interval * 1000L);
              } catch (Exception ex) {
                // ignore this exception.
              }
            }
          }
        };
    cleanupThread.setName("清理内存性能数据线程");
    cleanupThread.start();
  }

  public void stop() {
    isStart = false;
    if (cleanupThread != null) {
      try {
        cleanupThread.interrupt();
        Thread.yield();
      } catch (Exception ex) {
        ex.printStackTrace();
      }
    }
  }

  private void cleanupData() {

    log.iLog("开始清理4小时前内存性能数据...");

    // 执行创建
    // 建表
    PreparedStatement ps = null;
    Connection conn = null;
    try {
      // 执行查询
      conn = this.ds.getConnection();
      ps = conn.prepareStatement(this.cleanSql);
      ps.setTimestamp(1, new Timestamp(System.currentTimeMillis() - interval * 1000L));
      int dc = ps.executeUpdate();
      log.iLog("清理4小时前内存性能数据" + dc + "条。");
    } catch (SQLException e) {
      log.eLog("清理4小时前内存性能数据时失败: " + e.getMessage(), e);

    } finally {
      DBUtils.closeAll(conn, ps, null);
    }

    log.iLog("清理4小时前内存性能数据完毕。");
  }
}