package com.brilliance.mda.runtime.mda.driver.compile.component;

import com.brilliance.mda.runtime.mda.*;
import com.brilliance.mda.runtime.mda.driver.MdaDriver;
import com.brilliance.mda.runtime.mda.util.MdaUtils;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@AllArgsConstructor
public class RuleItemExecutor implements Ruleable<Boolean> {
    private static Logger log = LoggerFactory.getLogger(RuleItemExecutor.class);

    private RuleItem ruleItem;
    private IRuleEmitter ruleEmitter;
    private IModule root;

    public Boolean exec(){

        IModule module = (IModule) MdaDriver.getBaseObject(root,ruleItem.getDotPath());
        Object rs = null;
        if(module instanceof IModuleList && "executeDefault".equals(ruleItem.getMethodName())){
            ((IModuleList)module).executeDefault();
            return true;
        }else if(module instanceof IModuleList && "executeInit".equals(ruleItem.getMethodName())){
            ((IModuleList)module).executeInit();
            return true;
        }
        else if(ruleItem.getMethod() instanceof Method){
            try {
                boolean invoke = (boolean) (((Method) ruleItem.getMethod()).invoke(module));
                return invoke;
            }catch (RulePromptException e) {
                return true;
            }catch(IllegalAccessException e){

            }catch (InvocationTargetException e){
                if(e.getCause() instanceof RuntimeException){
                    throw (RuntimeException)e.getCause();
                }
            }
            return false;
        }
        else {
            rs = MdaUtils.invoke(module, ruleItem.getMethodName());
        }
        if(rs == null ){
            return false;
        }
        return (Boolean)rs;
    }

    public RuleItem getRuleItem() {
        return ruleItem;
    }

    public IRuleEmitter getRuleEmitter() {
        return ruleEmitter;
    }

    public IModule getRoot() {
        return root;
    }
}
