package jp.agentec.abook.abv.bl.logic;

import org.json.adf.JSONObject;

import java.util.Date;

import jp.agentec.abook.abv.bl.acms.client.AcmsClient;
import jp.agentec.abook.abv.bl.acms.client.json.UnlockReportJSON;
import jp.agentec.abook.abv.bl.acms.client.parameters.UnlockReportParameters;
import jp.agentec.abook.abv.bl.common.ABVEnvironment;
import jp.agentec.abook.abv.bl.common.nw.NetworkAdapter;
import jp.agentec.abook.abv.bl.data.dao.AbstractDao;
import jp.agentec.abook.abv.bl.data.dao.TaskReportDao;
import jp.agentec.adf.util.DateTimeFormat;
import jp.agentec.adf.util.DateTimeUtil;

import static java.net.HttpURLConnection.HTTP_OK;
import static jp.agentec.abook.abv.bl.acms.client.json.OperationDataJSON.ReportStartDate;
import static jp.agentec.abook.abv.bl.acms.client.json.OperationDataJSON.ReportStatus;
import static jp.agentec.abook.abv.bl.acms.client.json.OperationDataJSON.TaskReportId;

public class UnlockReportLogic extends AbstractLogic {

    public static UnlockReportLogic newInstance() {
        return new UnlockReportLogic();
    }

    public Result unlock(String taskKey, Long taskReportId, Date reportStartDate) {
        Result r = sendUnlockReport(taskKey, taskReportId, reportStartDate);
        if (r.result == 0 || r.extParam.reportStatus == 3) {
            updateLocalDB(taskKey, taskReportId, reportStartDate, r.extParam.getReportStatus());
        }
        return r;
    }

    private Result sendUnlockReport(
            String taskKey,
            Long taskReportId,
            Date reportStartDate
    ) {
        NetworkAdapter adapter = ABVEnvironment.getInstance().networkAdapter;
        AcmsClient client = AcmsClient.getInstance(cache.getUrlPath(), adapter);
        UnlockReportParameters param = new UnlockReportParameters(
                cache.getMemberInfo().sid,
                taskKey,
                taskReportId,
                reportStartDate
        );

        if (!networkAdapter.isNetworkConnected()) {
            // オフラインだったら、ロック成功扱い
            return Result.offLine(taskReportId, reportStartDate);
        }

        try {
            UnlockReportJSON reportJSON = client.sendUnlockReport(param);
            return Result.succsess(reportJSON, taskReportId, reportStartDate);
        } catch (Exception e) {
            return Result.failure(e, taskReportId, reportStartDate);
        }
    }

    private void updateLocalDB(
            String taskKey,
            Long taskReportId,
            Date reportStartDate,
            int reportStatus
    ) {
        // ローカルDBに反映
        TaskReportDao dao = AbstractDao.getDao(TaskReportDao.class);
        dao.updateReportLock(
                taskKey,
                taskReportId,
                reportStartDate,
                reportStatus,
                null,
                null,
                null
        );
    }

    // コールバック用のパラメータ
    public static class Result {
        public static final int BAD_STATUS = 999;
        int result;
        String message;
        ExtParam extParam;

        static Result succsess(UnlockReportJSON reportJSON, Long taskReportId, Date reportStartDate) {
            // 成功したとき
            Result result = new Result();
            result.result = reportJSON.httpStatus == HTTP_OK ? 0 : 1;
            result.message = "";
            result.extParam = new ExtParam(reportJSON.getReportStatus(), taskReportId, reportStartDate);
            return result;
        }

        static Result failure(Throwable e, Long taskReportId, Date reportStartDate) {
            // 例外がでたとき
            Result result = new Result();
            result.result = 1;
            result.message = e.getLocalizedMessage();
            result.extParam = new ExtParam(BAD_STATUS, taskReportId, reportStartDate);
            return result;
        }

        static Result offLine(Long taskReportId, Date reportStartDate) {
            // オフラインは成功扱い
            Result result = new Result();
            result.result = 0;
            result.message = "";
            result.extParam = new ExtParam(3, taskReportId, reportStartDate);
            return result;
        }

        public int getResult() {
            return result;
        }

        public String getMessage() {
            return message;
        }

        public ExtParam getExtParam() {
            return extParam;
        }
    }

    public static class ExtParam {
        int reportStatus ;
        Long taskReportId;
        Date reportStartDate;

        ExtParam(int reportStatus, Long taskReportId, Date reportStartDate) {
            this.reportStatus = reportStatus;
            this.taskReportId = taskReportId;
            this.reportStartDate = reportStartDate;
        }

        public int getReportStatus() {
            return reportStatus;
        }

        public String json() {
            JSONObject extParam = new JSONObject();
            extParam.put(ReportStatus, String.valueOf(reportStatus));
            if (taskReportId != null && taskReportId != 0) {
                extParam.put(TaskReportId, taskReportId);
            }
            if (reportStartDate != null) {
                extParam.put(ReportStartDate, DateTimeUtil.toStringInTimeZone(reportStartDate, DateTimeFormat.yyyyMMddHHmmss_hyphen, "UTC"));
            }
            return extParam.toString();
        }
    }
}
