package easydo.technology.core.controllers;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.fastjson.JSONObject;

import easydo.technology.core.EasydoCoreDevice.EasydoDevice;
import easydo.technology.core.EasydoCoreDevice.EasydoSensor;
import easydo.technology.core.EasydoCoreDevice.EasydoSensorRecord;
import easydo.technology.core.ZeroCoreSpringController;
import easydo.technology.core.processors.EasydoDeviceProcessor;
import zmo.technology.lite.core.ZeroException;
import zmo.technology.lite.core.ZeroQuery;
import zmo.technology.lite.core.ZeroQueryOperation;
import zmo.technology.lite.core.ZeroRequest;
import zmo.technology.lite.core.ZeroRequestGuider;

// @Controller
// @RequestMapping(EasydoDeviceController.DEVICE_PREFIX)
public class EasydoDeviceController extends ZeroCoreSpringController {

    public static final String DEVICE_PREFIX = "device";

    public EasydoDeviceController() {
        super(DEVICE_PREFIX);
    }

    @Autowired
    private DataSource dataSource;

    @Override
    protected String handlerNameConstructor(ZeroRequestGuider guider) throws Exception {
        if (guider.getPaths().size() != 1)
            throw new ZeroException(404, "no handlers");
        return guider.getPaths().get(0);
    }

    @RequestMapping(GENERAL_HANDLER_PATH)
    public void general(HttpServletRequest request, HttpServletResponse response) throws Exception {
        proxyHandler(dataSource, request, response);
    }

    public void add(ZeroRequestGuider guider) throws Exception {
        ZeroRequest<EasydoDevice> request = ZeroRequest.build(EasydoDevice.class, guider.getRawData());
        EasydoDeviceProcessor processor = EasydoDeviceProcessor.build(guider);
        for (EasydoDevice device : request.getQuerys())
            processor.addDeivce(device);
        guider.write(success());
    }

    public void up(ZeroRequestGuider guider) throws Exception {
        ZeroRequest<EasydoDevice> request = ZeroRequest.build(EasydoDevice.class, guider.getRawData());
        EasydoDeviceProcessor processor = EasydoDeviceProcessor.build(guider);
        for (EasydoDevice device : request.getQuerys())
            processor.upDeivce(device);
        guider.write(success());
    }

    public void rm(ZeroRequestGuider guider) throws Exception {
        ZeroRequest<EasydoDevice> request = ZeroRequest.build(EasydoDevice.class, guider.getRawData());
        EasydoDeviceProcessor processor = EasydoDeviceProcessor.build(guider);
        for (EasydoDevice device : request.getQuerys())
            processor.rmDeivce(device);
        guider.write(success());
    }

    public void addsensor(ZeroRequestGuider guider) throws Exception {
        ZeroRequest<EasydoSensor> request = ZeroRequest.build(EasydoSensor.class, guider.getRawData());
        EasydoDeviceProcessor processor = EasydoDeviceProcessor.build(guider);
        for (EasydoSensor sensor : request.getQuerys()) {
            processor.addSensor(sensor);
        }
        guider.write(success());
    }

    public void rmsensor(ZeroRequestGuider guider) throws Exception {
        ZeroRequest<EasydoSensor> request = ZeroRequest.build(EasydoSensor.class, guider.getRawData());
        EasydoDeviceProcessor processor = EasydoDeviceProcessor.build(guider);
        for (EasydoSensor sensor : request.getQuerys()) {
            processor.rmSensor(sensor);
        }
        guider.write(success());
    }

    protected static final String OPTION_SENSOR = "sensor";

    public void fetch(ZeroRequestGuider guider) throws Exception {

        ZeroRequest<ZeroQuery<EasydoDevice>> request = ZeroRequest.build(guider.getRawData(),
                EasydoDevice.class);

        ZeroQueryOperation<EasydoDevice> operation = ZeroQueryOperation.build(EasydoDevice.class, guider);
        operation.openConnect(request.getQuerys().get(0).setTableName("easydo_project"));

        List<EasydoDevice> datas = new ArrayList<>();
        JSONObject expands = new JSONObject();
        EasydoDeviceProcessor processor = EasydoDeviceProcessor.build(guider);

        operation.exec(() -> {
            EasydoDevice data = operation.getCurrent();
            if (request.hasOption(OPTION_SENSOR))
                processor.fetchSensorByDeviceID(data);
            processor.fetchDeivceHealth(data);
            datas.add(data);
        }).eachExpands((key, value) -> expands.put(key, value));
        guider.write(success(datas, expands));
    }

    public void devsen(ZeroRequestGuider guider) throws Exception {

        ZeroRequest<ZeroQuery<EasydoSensor>> request = ZeroRequest.build(guider.getRawData(),
                EasydoSensor.class);

        ZeroQueryOperation<EasydoSensor> operation = ZeroQueryOperation.build(EasydoSensor.class, guider);
        operation.openConnect(request.getQuerys().get(0).setTableName("easydo_sensor"));

        List<EasydoSensor> datas = new ArrayList<>();
        JSONObject expands = new JSONObject();
        EasydoDeviceProcessor processor = EasydoDeviceProcessor.build(guider);

        operation.exec(() -> {
            EasydoSensor data = operation.getCurrent();
            data.setDevice(processor.fetchDeviceByID(data.getDevice().uuIDString()));
            datas.add(data);
        }).eachExpands((key, value) -> expands.put(key, value));
        guider.write(success(datas, expands));
    }

    public void senrec(ZeroRequestGuider guider) throws Exception {

        ZeroRequest<ZeroQuery<EasydoSensorRecord>> request = ZeroRequest.build(guider.getRawData(),
                EasydoSensorRecord.class);

        ZeroQueryOperation<EasydoSensorRecord> operation = ZeroQueryOperation.build(EasydoSensorRecord.class, guider);
        operation.openConnect(request.getQuerys().get(0).setTableName("easydo_sensor_record"));

        List<EasydoSensorRecord> datas = new ArrayList<>();
        JSONObject expands = new JSONObject();
        EasydoDeviceProcessor processor = EasydoDeviceProcessor.build(guider);

        operation.exec(() -> {
            EasydoSensorRecord data = operation.getCurrent();
            data.setSensor(processor.fetchSensorByID(data.getSensor().uuIDString()));
            data.getSensor().setDevice(processor.fetchDeviceByID(data.getSensor().getDevice().uuIDString()));
            datas.add(data);
        }).eachExpands((key, value) -> expands.put(key, value));
        guider.write(success(datas, expands));
    }
}
