
import { actionAddins } from ".";
import { IField, IAction,IActionResult, IActionNode, IActionProperty, IContext, IVarName } from "../types/ActionTypes";
import { Formatter } from "../util/format";

declare global {
    interface Window { $format: any; }  
}

interface IAutoNumberingProps{
    //文書番号を格納する
    field:IField;
    format:string;
    prefix:string;
    suffix:string;
    verName:IVarName;
}

export class AutoNumbering implements IAction{
    name: string;
    actionProps: IActionProperty[];
    props:IAutoNumberingProps;
    constructor(){
        this.name="自動採番する";
        this.actionProps=[];
        this.register();
        this.props={
            field:{code:''},
            format:'',
            prefix:'',
            suffix:'',
            verName:{name:''}
        }
        globalThis.window.$format=this.format;
        this.register();
    }
/**
 * アクションの処理を実装する
 * @param actionNode アクションノード
 * @param event Kintoneのイベント
 * @param context コンテキスト（レコード、変数情報を持っている）
 * @returns 
 */
    async process(actionNode:IActionNode,event:any,context:IContext):Promise<IActionResult> {
        let result={
            canNext:false,
            result:false
        };
        try{
            this.actionProps=actionNode.actionProps;
            if (!('field' in actionNode.ActionValue) && !('format' in actionNode.ActionValue)) {
                return result
            }
            this.props = actionNode.ActionValue as IAutoNumberingProps;
            const record = event.record;
            const docNum = await this.createNumber(this.props);
            record[this.props.field.code].value=docNum;
            //変数設定
            if(this.props.verName && this.props.verName.name!==''){
                context.variables[this.props.verName.name]=docNum;
            }
            result= {
              canNext:true,
              result:true
            }
            return result;
        }catch(error){
            context.errors.handleError(error,actionNode);
            return {
                canNext:false,
                result:false
            }
        }
    }

    execTemplate(template:string):string{
        if(template===undefined) return '';
        const regex = /\$\{([^}]+)\}/g;
        return template.replace(regex,(match,expr)=>{
            return this.execEval(match,expr);
        });
    }

    execEval(match:string,expr:string):string{
        console.log(match);
        // @ts-ignore
        return eval(expr);
    }

    format(pattern:string):string{
        const now=new Date();
        return Formatter.dateFormat(now, pattern);
    }

    async createNumber(props:IAutoNumberingProps){
        let number :string='';
        let prefix:string='';
        let suffix:string='';
        let no=1;     
        try{
            no = await this.fetchNo();
        }catch(error){
            console.log(error);
        }
        if(props.format!==undefined && props.format!==''){
            number=Formatter.numberFormat(no, props.format);
        }else{
            number=no.toString(10);
        }

        if(props.prefix!==undefined && props.prefix!==''){
            prefix=this.execTemplate(props.prefix);
        }

        if(props.suffix!==undefined && props.suffix!==''){
            suffix=this.execTemplate(props.suffix);
        }
        return `${prefix}${number}${suffix}`;
    }

    async fetchNo():Promise<number>{
        let recNo=1;

        return await new kintone.Promise<number>((resolve,reject)=>{
            const appurl = kintone.api.url('/k/v1/records',true);
            const params={
                app:kintone.app.getId(),
                fields:['$id'],
                query:'limit 1'
            };
            return kintone.api(appurl,'GET',params).then((resp)=>{
                if(resp.records[0]!==null){
                    recNo = parseInt(resp.records[0].$id.value,10)+1;
                }
                resolve(recNo);
            }).catch((error)=>{
                reject(error);
            });
        });
    }

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