package cn.reghao.autodop.dagent.rpc.impl;

import cn.reghao.autodop.common.dagent.app.log.AppLogArgs;
import cn.reghao.autodop.common.dagent.app.log.LogConfig;
import cn.reghao.autodop.common.dagent.app.log.LogFile;
import cn.reghao.autodop.common.msg.rpc.dto.app.*;
import cn.reghao.autodop.common.msg.rpc.RpcPayload;
import cn.reghao.autodop.common.msg.rpc.RpcResult;
import cn.reghao.autodop.common.msg.rpc.clazz.AppRpcClazz;
import cn.reghao.autodop.common.util.ExceptionUtil;
import cn.reghao.autodop.dagent.app.AppService;
import cn.reghao.autodop.dagent.app.DockerAppServiceImpl;
import cn.reghao.autodop.dagent.app.ZipAppServiceImpl;
import cn.reghao.jdkutil.machine.MachineId;
import cn.reghao.jdkutil.result.Result;
import cn.reghao.jdkutil.result.ResultStatus;
import cn.reghao.jdkutil.serializer.JsonConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author reghao
 * @date 2020-12-30 10:26:47
 */
@Slf4j
@Component
public class AppClazzRpcImpl {
    private final AppService dockerAppServiceImpl;
    private final AppService zipAppServiceImpl;
    
    public AppClazzRpcImpl() {
        this.dockerAppServiceImpl = new DockerAppServiceImpl();
        this.zipAppServiceImpl = new ZipAppServiceImpl();
    }
    
    public RpcResult process(RpcPayload rpcPayload) {
        String method = rpcPayload.getMethod();
        String jsonParam = rpcPayload.getJsonParam();
        Object param;
        switch (AppRpcClazz.valueOf(method)) {
            case deploy:
                param = JsonConverter.jsonToObject(jsonParam, DeployParam.class);
                return deploy(param);
            case status:
                param = JsonConverter.jsonToObject(jsonParam, AppIdParam.class);
                return status(param);
            case start:
                param = JsonConverter.jsonToObject(jsonParam, AppIdParam.class);
                return start(param);
            case stop:
                param = JsonConverter.jsonToObject(jsonParam, AppIdParam.class);
                return stop(param);
            case restart:
                param = JsonConverter.jsonToObject(jsonParam, AppIdParam.class);
                return restart(param);
            default:
                String err = String.format("找不到 %s 方法", method);
                return RpcResult.error(err);
        }
    }
    
    private RpcResult deploy(Object param) {
        DeployParam deployParam = (DeployParam) param;
        String buildLogId = deployParam.getBuildLogId();
        String packType = deployParam.getPackType();

        AppStatus appStatus;
        DeployResult deployResult = new DeployResult(buildLogId, MachineId.id(), MachineId.ipv4());
        try {
            switch (PackType.valueOf(packType)) {
                case docker:
                    appStatus = dockerAppServiceImpl.deploy(deployParam);
                    deployResult.setResult(Result.result(ResultStatus.SUCCESS));
                    deployResult.setAppStatus(appStatus);
                    break;
                case zip:
                    appStatus = zipAppServiceImpl.deploy(deployParam);
                    deployResult.setResult(Result.result(ResultStatus.SUCCESS));
                    deployResult.setAppStatus(appStatus);
                    break;
                default:
                    String msg = "打包类型 " + deployParam.getPackType() + " 不存在";
                    deployResult.setResult(Result.result(ResultStatus.ERROR, msg));
            }
        } catch (Exception e) {
            deployResult.setResult(Result.result(ResultStatus.FAIL, ExceptionUtil.errorMsg(e)));
        }
        
        return RpcResult.success(JsonConverter.objectToJson(deployResult));
    }

    public RpcResult status(Object param) {
        AppIdParam appIdParam = (AppIdParam) param;
        String appId = appIdParam.getAppId();
        String packerType = appIdParam.getPackerType();

        AppStatus appStatus;
        try {
            switch (PackType.valueOf(packerType)) {
                case docker:
                    appStatus = dockerAppServiceImpl.status(appId);
                    break;
                case zip:
                    appStatus = zipAppServiceImpl.status(appId);
                    break;
                default:
                    return RpcResult.error("打包类型 " + appIdParam.getPackerType() + " 不存在");
            }
        } catch (Exception e) {
            return RpcResult.fail(ExceptionUtil.errorMsg(e));
        }
        
        return RpcResult.success(JsonConverter.objectToJson(appStatus));
    }

    public RpcResult restart(Object param) {
        AppIdParam appIdParam = (AppIdParam) param;
        String appId = appIdParam.getAppId();
        String packerType = appIdParam.getPackerType();

        AppStatus appStatus;
        try {
            switch (PackType.valueOf(packerType)) {
                case docker:
                    appStatus = dockerAppServiceImpl.restart(appId);
                    break;
                case zip:
                    appStatus = zipAppServiceImpl.restart(appId);
                    break;
                default:
                    return RpcResult.error("打包类型 " + appIdParam.getPackerType() + " 不存在");
            }
        } catch (Exception e) {
            return RpcResult.fail(ExceptionUtil.errorMsg(e));
        }
        
        return RpcResult.success(JsonConverter.objectToJson(appStatus));
    }

    public RpcResult stop(Object param) {
        AppIdParam appIdParam = (AppIdParam) param;
        String appId = appIdParam.getAppId();
        String packerType = appIdParam.getPackerType();

        AppStatus appStatus;
        try {
            switch (PackType.valueOf(packerType)) {
                case docker:
                    appStatus = dockerAppServiceImpl.stop(appId);
                    break;
                case zip:
                    appStatus = zipAppServiceImpl.stop(appId);
                    break;
                default:
                    return RpcResult.error("打包类型 " + appIdParam.getPackerType() + " 不存在");
            }
        } catch (Exception e) {
            return RpcResult.fail(ExceptionUtil.errorMsg(e));
        }

        return RpcResult.success(JsonConverter.objectToJson(appStatus));
    }

    public RpcResult start(Object param) {
        AppIdParam appIdParam = (AppIdParam) param;
        String appId = appIdParam.getAppId();
        String packerType = appIdParam.getPackerType();

        AppStatus appStatus;
        try {
            switch (PackType.valueOf(packerType)) {
                case docker:
                    appStatus = dockerAppServiceImpl.start(appId);
                    break;
                case zip:
                    appStatus = zipAppServiceImpl.start(appId);
                    break;
                default:
                    return RpcResult.error("打包类型 " + appIdParam.getPackerType() + " 不存在");
            }
        } catch (Exception e) {
            return RpcResult.fail(ExceptionUtil.errorMsg(e));
        }

        return RpcResult.success(JsonConverter.objectToJson(appStatus));
    }

    public RpcResult log(Object param) {
        AppLogArgs appLogArgs = (AppLogArgs) param;
        String packerType = appLogArgs.getPackerType();
        long count = appLogArgs.getLogConfigs().stream().filter(LogConfig::getIsDir).count();
        try {
            switch (PackType.valueOf(packerType)) {
                case docker:
                    if (count > 0) {
                        List<LogFile> logFiles = dockerAppServiceImpl.logFiles(appLogArgs);
                        return RpcResult.success(JsonConverter.objectToJson(logFiles));
                    } else {
                        List<String> logContent = dockerAppServiceImpl.logContent(appLogArgs);
                        return RpcResult.success(JsonConverter.objectToJson(logContent));
                    }
                case zip:
                    if (count > 0) {
                        List<LogFile> logFiles = zipAppServiceImpl.logFiles(appLogArgs);
                        return RpcResult.success(JsonConverter.objectToJson(logFiles));
                    } else {
                        List<String> logContent = zipAppServiceImpl.logContent(appLogArgs);
                        return RpcResult.success(JsonConverter.objectToJson(logContent));
                    }
                default:
                    return RpcResult.error("打包类型 " + appLogArgs.getPackerType() + " 不存在");
            }
        } catch (Exception e) {
            return RpcResult.fail(ExceptionUtil.errorMsg(e));
        }
    }
}
