
import { Record } from "@kintone/rest-api-client/lib/src/client/types";
import { actionAddins } from ".";
import {  IAction,IActionResult, IActionNode, IActionProperty, IField, IContext } from "../types/ActionTypes";
import { ConditionTree } from '../types/Conditions';

type TextStyle = "太字" | "斜体" | "下線" | "打ち消し線";
type StyleRigion = "書式変更フィールド" | "行全体"|"";


/**
 * アクションの属性定義
 */
interface IStyleFieldProps{
    field:IField;
    fontColor:string; 
    bgColor:string;
    fontStyle:TextStyle[];
    allRow:StyleRigion;
    condition:string;
}
/**
 * 条件書式表示アクション
 */
export class StyleFieldAction implements IAction{
    name: string;
    actionProps: IActionProperty[];
    props:IStyleFieldProps;
    constructor(){
        this.name="条件書式表示";
        this.actionProps=[];
       this.props={
            field:{code:''},
            fontColor:'',
            bgColor:'',
            fontStyle:[],
            allRow:'',
            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) && !('allRow' in actionNode.ActionValue)) {
                return result
            }
            this.props = actionNode.ActionValue as IStyleFieldProps;
            //書式設定
            console.log(event.type)
            if (event.type === "app.record.index.show") {
              this.setStyleForView(event, this.props, context);
            } else if (event.type === "app.record.detail.show") {
              this.setStyleForDetail(event, this.props, context);
            } else if (
              event.type.includes("app.record.create.change.") ||
              event.type.includes("app.record.edit.change.")
            ) {
              this.setStyleForEdit(event, this.props, context);
            }
            result= {
                canNext:true,
                result:true
            }
            return result;
        }catch(error){
            context.errors.handleError(error,actionNode);
            result.canNext=false;
            return result;
        }

    }

    setStyleForEdit(event:any,props:IStyleFieldProps,context:IContext){
        const recordTable = document.getElementById('record-gaia');
        if (recordTable) {
            Array.from(
              recordTable.getElementsByTagName("span")
            )
              .filter((span) => span.innerText === props.field.code)
              .map((span) =>
                span.parentElement?.nextElementSibling
                  ?.querySelector(".input-text-outer-cybozu")
                  ?.firstElementChild as HTMLElement | null
              )
              .filter((inputElement): inputElement is HTMLElement => !!inputElement)
              .forEach((inputElement) => {
                const conditionResult = this.getConditionResult(
                  this.getCondition(props.condition),
                  context
                );
                
                if (conditionResult) {
                  this.setFieldStyle(props, inputElement);
                } else {
                  inputElement.removeAttribute('style');
                }
              });
        }
    }
    
    

    /**
     * 詳細表示時のスタイル設定
     * @param event 
     * @param props 
     * @param context 
     * @returns 
     */
    setStyleForDetail(event:any,props:IStyleFieldProps,context:IContext){
        const elem = kintone.app.record.getFieldElement(props.field.code);
        if(!elem){
            return;
        } 
        const tree = this.getCondition(props.condition);
        const conditionResult = this.getConditionResult(tree,context);
        if(conditionResult){
            this.setFieldStyle(props,elem);
        }
    }

    /**
     * 一覧表示時の書式設定
     * @param event 
     * @param props 
     * @param context 
     * @returns 
     */
    setStyleForView(event:any,props:IStyleFieldProps,context:IContext){
        const records:Record[] = event.records;
        const cells = kintone.app.getFieldElements(props.field.code);
        if(!cells){
            return;
        }
        let elem :HTMLElement|null;
        const conditionTree = this.getCondition(props.condition);
        records.forEach((record:Record,index:number) => {
            const currContext:IContext = {
                variables:context.variables,
                record:record,
                errors:context.errors
            }
            const conditionResult = this.getConditionResult(conditionTree,currContext);
            if(conditionResult){
                elem = cells[index];
                if(props.allRow==="行全体"){
                    elem = cells[index].parentElement;
                }
                if(elem){
                    this.setFieldStyle(props,elem);
                }
            }
        });
    }

    /**
     * 
     * @param props HtmlElement書式設定
     */
    setFieldStyle(props:IStyleFieldProps,elem:HTMLElement){
       
            if(props.fontColor){
                elem.style.color=props.fontColor;
            }
            if(props.bgColor){
                elem.style.backgroundColor=props.bgColor;
            }
            if(props.fontStyle.length>0){
                if(props.fontStyle.includes("斜体")){
                    elem.style.fontStyle="italic";
                }
 
                if(props.fontStyle.includes("太字")){
                    elem.style.fontWeight = "bold";
                }
                let textDecoration="";
                if(props.fontStyle.includes("下線")){
                    textDecoration="underline";
                }
                if(props.fontStyle.includes("打ち消し線")){
                    textDecoration = textDecoration? textDecoration + " line-through":"line-through";
                }
                if(textDecoration){
                    elem.style.textDecoration=textDecoration;
                }
            }
    }

    /**
     * 条件式を実行する
     * @param tree 条件式オブジェクト
     * @param context 
     * @returns 
     */
    getConditionResult(tree:ConditionTree|null, context:any):boolean{
        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 StyleFieldAction();