package easydo.technology.core.processors;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;

import com.alibaba.fastjson.JSONObject;

import easydo.technology.core.DeviceStock;
import zmo.technology.lite.core.ZeroProcessor;
import zmo.technology.lite.core.ZeroRequestGuider;

public class DeviceProcessor extends ZeroProcessor {

    protected DeviceProcessor(ZeroRequestGuider guider) {
        super(guider);
    }

    public static DeviceProcessor build(ZeroRequestGuider guider) {
        return new DeviceProcessor(guider);
    }

    //// device

    private PreparedStatement fetchDeviceByIDPrepared() throws SQLException {
        final String fetchDeviceByID = "SELECT * FROM device_stock_view WHERE id = ?";
        if (!existsPreparedStatement(fetchDeviceByID))
            registeyPreparedStatement(fetchDeviceByID);
        return preparedStatement(fetchDeviceByID);
    }

    public DeviceStock fetchDeviceByID(long deviceID) throws SQLException {
        fetchDeviceByIDPrepared().setLong(1, deviceID);
        ResultSet set = fetchDeviceByIDPrepared().executeQuery();
        if (!set.next())
            throw new SQLException("device id '" + deviceID + "' not found");
        return new DeviceStock(set);
    }

    private PreparedStatement fetchDevicePrepared() throws SQLException {
        final String fetchDevice = "SELECT * FROM device_stock_view WHERE device_num = ?";
        if (!existsPreparedStatement(fetchDevice))
            registeyPreparedStatement(fetchDevice);
        return preparedStatement(fetchDevice);
    }

    public DeviceStock fetchDevice(String deviceNum) throws SQLException {
        fetchDevicePrepared().setString(1, deviceNum);
        ResultSet set = fetchDevicePrepared().executeQuery();
        if (!set.next())
            throw new SQLException("device '" + deviceNum + "' not found");
        return new DeviceStock(set);
    }

    ///// healthbeat

    private PreparedStatement addHealthbeatPrepared() throws SQLException {
        final String addHealthbeat = "INSERT INTO device_healthbeat(features, device_id) VALUES (? ,?)";
        if (!existsPreparedStatement(addHealthbeat))
            registeyPreparedStatement(addHealthbeat);
        return preparedStatement(addHealthbeat);
    }

    private PreparedStatement upHealthbeatPrepared() throws SQLException {
        final String upHealthbeat = "UPDATE device_healthbeat SET features = ? WHERE device_id = ? AND ID <> ''";
        if (!existsPreparedStatement(upHealthbeat))
            registeyPreparedStatement(upHealthbeat);
        return preparedStatement(upHealthbeat);
    }

    private PreparedStatement fetchHealthbeatCountPrepared() throws SQLException {
        final String fetchHealthbeatCount = "SELECT count(1) FROM device_healthbeat WHERE device_id = ? LIMIT 1";
        if (!existsPreparedStatement(fetchHealthbeatCount))
            registeyPreparedStatement(fetchHealthbeatCount);
        return preparedStatement(fetchHealthbeatCount);
    }

    public void onHealthbeat(JSONObject features, long deviceID) throws SQLException {
        fetchHealthbeatCountPrepared().setLong(1, deviceID);
        ResultSet set = fetchHealthbeatCountPrepared().executeQuery();
        if (!set.next())
            throw new SQLException("query 'fetchHealthbeatCount' faild");

        if (set.getLong(1) > 0) {
            upHealthbeatPrepared().setString(1, JSONObject.toJSONString(features));
            upHealthbeatPrepared().setLong(2, deviceID);
            upHealthbeatPrepared().execute();
        } else {
            addHealthbeatPrepared().setString(1, JSONObject.toJSONString(features));
            addHealthbeatPrepared().setLong(2, deviceID);
            addHealthbeatPrepared().execute();
        }

    }

    private PreparedStatement fetchHealthbeatPrepared() throws SQLException {
        final String fetchHealthbeat = "SELECT update_time FROM device_healthbeat WHERE device_id = ? LIMIT 1";
        if (!existsPreparedStatement(fetchHealthbeat))
            registeyPreparedStatement(fetchHealthbeat);
        return preparedStatement(fetchHealthbeat);
    }

    public Date fetchHealthbeat(long deviceID) throws SQLException {
        fetchHealthbeatPrepared().setLong(1, deviceID);
        ResultSet set = fetchHealthbeatPrepared().executeQuery();
        if (!set.next())
            throw new SQLException("device '" + deviceID + "' not found");
        return new Date(set.getTimestamp(1).getTime());
    }
}
