package net.northking.cctp.element.test;

import net.northking.cctp.element.core.IExecuteContext;
import net.northking.cctp.element.core.IScriptStep;
import net.northking.cctp.element.core.IStepTarget;
import net.northking.cctp.element.core.ITestTarget;
import net.northking.cctp.element.core.exception.ExecuteException;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * SampleExecuteContext
 *
 * @author fengxiang.zhang
 * @since 1.0
 */
public class SampleExecuteContext implements IExecuteContext {

    private Map<String, String> variableMap = new HashMap<>();
    private Map<String, String> globalVariableMap = new HashMap<>();
    private Map<Class, Object> serviceMap = new HashMap<>();
    private Map<String, Object> contextVariableMap = new HashMap<>();
    private IScriptStep currentStep;
    private IExecuteContext parentContext;

    private Map<String, String> variableDefineMap = new HashMap<>();
    private Map<String, String> globalVariableDefineMap = new HashMap<>();

    private SampleExecuteContext() {
    }

    @Override
    public void setVariable(String key, String value) {
        variableMap.put(key, value);
    }

    @Override
    public String getVariable(String key) {
        return variableMap.get(key);
    }

    /**
     * 获取变量对应的值
     *
     * @param var
     * @return
     */
    @Override
    public String getVariableValue(String var) {
        return null;
    }

    @Override
    public void setProjectGlobalVariable(String key, String val) {
        globalVariableMap.put(key, val);
    }

    @Override
    public String getProjectGlobalVariable(String key) {
        return globalVariableMap.get(key);
    }

    @Override
    public <T> T getService(Class<T> serviceClz) {
        return (T) serviceMap.get(serviceClz);
    }

    @Override
    public String[] getAllContextNames() {
        return new String[0];
    }

    @Override
    public Object getContextVariable(String key) {
        return contextVariableMap.get(key);
    }

    @Override
    public IExecuteContext getParentContext() {
        return this.parentContext;
    }

    @Override
    public IScriptStep getCurrentStep() {
        return this.currentStep;
    }

    /**
     * 获取测试目标信息
     *
     * @return
     */
    @Override
    public ITestTarget[] getTestTarget() {
        return null;
    }

    @Override
    public String getVariableType(String key, boolean global) {
        String type = global ? globalVariableDefineMap.get(key) : variableDefineMap.get(key);
        if (type == null) {
            throw new ExecuteException("变量" + key + "未声明");
        }
        return type;
    }

    /**
     * 获取配置
     *
     * @param name 配置名称 例：spring.application.name
     * @return
     */
    @Override
    public String getProperty(String name) {
        return null;
    }

    /**
     * 获取配置，如果没有返回传入的默认值
     *
     * @param name         配置名称
     * @param defaultValue 默认值
     * @return
     */
    @Override
    public String getProperty(String name, String defaultValue) {
        return null;
    }

    /**
     * 获取设备信息
     *
     * @return
     */
    @Override
    public Map<String, Object> getDeviceInfo() {
        return null;
    }

    @Override
    public Object evalExpression(String expression) {
        return expression;
    }

    public void setCurrentStep(IScriptStep currentStep) {
        this.currentStep = currentStep;
    }

    public static class Builder {

        private SampleExecuteContext context = new SampleExecuteContext();
        private SampleScriptStep step = new SampleScriptStep();

        public Builder putVariable(String name, String value, String type) {
            context.variableMap.put(name, value);
            context.variableDefineMap.put(name, type);
            return this;
        }

        public Builder putGlobalVariable(String name, String value, String type) {
            context.globalVariableMap.put(name, value);
            context.globalVariableDefineMap.put(name, type);
            return this;
        }

        public Builder registerService(Class serviceClz, Object service) {
            context.serviceMap.put(serviceClz, service);
            return this;
        }

        public Builder putContextVariable(Map<String, Object> contextVariableMap) {
            context.contextVariableMap.putAll(contextVariableMap);
            return this;
        }

        public Builder putContextVariable(String name, Object value) {
            context.contextVariableMap.put(name, value);
            return this;
        }

        public Builder putStepArg(String name, String value) {
            step.putArg(name, value);
            return this;
        }

        public Builder putOutPut(String name, String value) {
            step.putOutPut(name, value);
            return this;
        }

        public Builder setParentContext(IExecuteContext parentContext) {
            context.parentContext = parentContext;
            return this;
        }

        public IExecuteContext build() {
            context.setCurrentStep(step);
            return context;
        }
    }

    public static class SampleScriptStep implements IScriptStep {

        private Map<String, String> argMap = new HashMap<>();
        private Map<String, String> outputMap = new HashMap<>();

        @Override
        public List<? extends IStepTarget> getTargets() {
            return null;
        }

        @Override
        public Map<String, String> getArgs() {
            return argMap;
        }

        @Override
        public Map<String, String> getOutput() {
            return outputMap;
        }

        public void putArg(String name, String value) {
            argMap.put(name, value);
        }

        public void putOutPut(String name, String value) {
            outputMap.put(name, value);
        }
    }

}
