
import { actionAddins } from ".";
import {  IAction,IActionResult, IActionNode, IActionProperty, IField, IContext } from "../types/ActionTypes";
import { ConditionTree } from '../types/Conditions';
/**
 * アクションの属性定義
 */
interface IDisableProps{
    //対象フィールド
    field:IField;
    //編集可/不可設定
    editable:'編集可'|'編集不可'|''; 
    condition:string;
}
/**
 * 編集可／不可アクション
 */
export class FieldDisableAction implements IAction{
    name: string;
    actionProps: IActionProperty[];
    props:IDisableProps;
    constructor(){
        this.name="編集可／不可";
        this.actionProps=[];
       this.props={
            field:{code:''},
            editable:'',
            condition:''
        }
        //アクションを登録する
        this.register();
    }
    /**
     * アクションの実行を呼び出す
     * @param actionNode 
     * @param event 
     * @returns 
     */
    async process(actionNode:IActionNode,event:any,context:IContext):Promise<IActionResult> {
        let result={
            canNext:true,
            result:false
        };
        try{
            //属性設定を取得する
            this.actionProps=actionNode.actionProps;
            if (!('field' in actionNode.ActionValue) && !('editable' in actionNode.ActionValue)) {
                return result
            }
            this.props = actionNode.ActionValue as IDisableProps;
            //条件式の計算結果を取得
            const conditionResult = this.getConditionResult(context);
            const record = event.record;
            if(!(this.props.field.code in record)){
                throw new Error(`フィールド「${this.props.field.code}」が見つかりません。`);
            }
            if(conditionResult){
                if(this.props.editable==='編集可'){
                    record[this.props.field.code].disabled=false;
                }else if (this.props.editable==='編集不可'){
                    record[this.props.field.code].disabled=true;
                }
            }
            result= {
            canNext:true,
            result:true
            }
            return result;
        }catch(error){
            context.errors.handleError(error,actionNode);
            result.canNext=false;
            return result;
        }

    }
    /**
     *
     * @param context 条件式を実行する
     * @returns
     */
    getConditionResult(context:any):boolean{
        const tree =this.getCondition(this.props.condition);
        if(!tree){
            //条件を設定されていません
            return true;
        }
        return tree.evaluate(tree.root,context);
    }

    /**
     * @param condition 条件式ツリーを取得する
     * @returns
     */
    getCondition(condition:string):ConditionTree|null{
        try{
            const tree = new ConditionTree();
            tree.fromJson(condition);
            if(tree.getConditions(tree.root).length>0){
                return tree;
            }else{
                return null;
            }
        }catch(error){
            return null;
        }
    }

    register(): void {
        actionAddins[this.name]=this;
    }
}
new FieldDisableAction();