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

//右UI画面propertyのname:型：
interface IStringJoinProps{
    //保存先フィールド
    saveField:IField;
    //結合元フィールド1
    joinField1:IField;
    //結合元フィールド2
    joinField2:IField;
    //区切り文字
    delimiter:string;
}

//IActionインタフェースを実装する新しいクラスActionを作成：
export class StringJoinAction implements IAction{
    name: string;
    //importから導入顕示定義
    actionProps: IActionProperty[];
    //上方のinterface Propsから、props受ける属性を定義：
    props:IStringJoinProps;
    //関数定義に必要な類名を構築：
    constructor(){
        //pgAdminDBに登録したアクション名(name/subtitle)一致する必要がある：
        this.name="文字結合";
        this.actionProps=[];
        this.register();
        //プロパティ属性初期化：
        this.props={
            saveField:{code:''},
            joinField1:{code:''},
            joinField2:{code:''},
            delimiter:''
        }
        //リセット上記登録表：
        this.register();
    }
/**
 * アクションの処理を実装する
 * @param actionNode アクションノード
 * @param event Kintoneのイベント
 * @param context コンテキスト（レコード、変数情報を持っている）
 * @returns 
 */
    //非同期処理ある関数下のある属性：
    async process(actionNode:IActionNode,event:any):Promise<IActionResult> {
        let result={
            //後継処理不可：
            canNext:false,
            result:false
        };
        try{
            //属性設定を取得する：
            this.actionProps=actionNode.actionProps;
            //プロパティ設定のデータ型は必要な情報含めますか？全部不存在時return:
            if (!('saveField' in actionNode.ActionValue) && !('joinField1' in actionNode.ActionValue) && !('joinField2' in actionNode.ActionValue)) {
                return result
            }

            //既定のプロパティのインタフェースへ変換：
            this.props = actionNode.ActionValue as IStringJoinProps;
            const record = event.record;

            //kintoneフィールドタイプ取得：
            const joinField1type=this.props.joinField1.type;
            const joinField2type=this.props.joinField2.type;
            const saveFieldtype=this.props.saveField.type;

//////////////////////////////////////////////////////////////////////////////////////////////////////
            // //保存先フィールドは文字列フィールドではない場合、エラー発生：
            if(!(saveFieldtype==='SINGLE_LINE_TEXT'||saveFieldtype==='MULTI_LINE_TEXT'||saveFieldtype==='RICH_TEXT')){
                event.error='[エラーメッセージ]：結合保存先対応不可。結合しません';
                if (event.type.includes('success')){
                    window.alert("[windows alert]："+event.error);
                }
                result = {
                    canNext: false,
                    result: false
                }
                return result;
            }
//////////////////////////////////////////////////////////////////////////////////////////
    //値取得方法定義：
    function getValue(value:string,type:string|undefined,fieldCode:string,event:any){
        if(event.record[fieldCode]?.value===undefined||event.record[fieldCode]?.value===null){
            event.record[fieldCode].value='';
        }
        //作成者、更新者：
        if(type==='CREATOR'||type==='MODIFIER'){
            value = event.record[fieldCode]?.value.name;
        //日時、作成日時、更新日時：
        }else if(type==='DATETIME'||type==='CREATED_TIME'||type==='UPDATED_TIME'){
            if(event.record[fieldCode]?.value!==undefined && event.record[fieldCode]?.value!==''){
                value = Formatter.dateFormat(new Date(event.record[fieldCode]?.value),'yyyy-MM-dd HH:mm');
                }else{
                    value=event.record[fieldCode]?.value;
                }
        //ユーザ選択、組織選択、グループ選択、添付ファイル名、作業者、カテゴリー：
        }else if(type==='USER_SELECT'||type==='ORGANIZATION_SELECT'||type==='GROUP_SELECT'||type==='FILE'||type==='STATUS_ASSIGNEE'){
            if(event.record[fieldCode]?.value===undefined || event.record[fieldCode]?.value===''){
                value = event.record[fieldCode]?.value;
            }else{
                const mototext=event.record[fieldCode]?.value;
                let arr=[];
                for(let i=0;i<mototext.length;i++){
                    arr.push(mototext[i].name);
                }
                //配列要素を,で連結して文字列を作成：
                value=arr.join();
            }
        //カテゴリー、チェックボックス、複数選択：
        }else if(type==='CATEGORY'||type==='CHECK_BOX'||type==='MULTI_SELECT'){
            if(event.record[fieldCode]?.value===undefined || event.record[fieldCode]?.value===''){
                value = event.record[fieldCode]?.value;
            }else{
                const mototext=event.record[fieldCode]?.value;
                let arr=[];
                for(let i=0;i<mototext.length;i++){
                    arr.push(mototext[i]);
                }
                //配列要素を,で連結して文字列を作成：
                value=arr.join();
            }
        //詳細画面プロセス実行後のステータス：
        }else if(type==='STATUS'&&event.type.includes('process')){
            value = event.nextStatus.value;
        }else{
            value = event.record[fieldCode]?.value;
        }
        if (value===undefined || value===null){
            value='';
        }        
        return value;     
    }
//////////////////////////////////////////////////////////////////////
            //値取得方法呼出：
            let joinValue1:string='';
            joinValue1=getValue(joinValue1,joinField1type,this.props.joinField1.code,event);
/////////////////////////////////////////////////////////////////////////////////////
            let joinValue2:string='';
            joinValue2=getValue(joinValue2,joinField2type,this.props.joinField2.code,event);
//////////////////////////////////////////////////////////////////////////////////////////////////////////
            const conString = this.props.delimiter;
            let saveValue:string='';
            //前後結合元が空白なら区切り文字も空白にする(例:1-8の8無いなら1。1-8の1無いなら8。1空白8の8無いなら1。結合元全部空白なら全部空白):
            if(joinValue1===''&&joinValue2===''){
                saveValue='';
            }else if(joinValue1===''&&joinValue2!==''){
                saveValue=joinValue2;
            }else if(joinValue2===''&&joinValue1!==''){
                saveValue=joinValue1;
            }else if(joinValue1!==''&&joinValue2!==''){
                saveValue=`${joinValue1}${conString}${joinValue2}`
            }
////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //新規/更新/一覧保存成功後の以外のeventでPUT使用しない：
            if (!event.type.includes('success')){
                 //保存先フィールドに値セット：
                 record[this.props.saveField.code].value=saveValue;
                 //window.alert("文字結合行いました。"+this.props.joinField1.name+":"+joinValue1+","+this.props.joinField2.name+":"+joinValue2+"。");
            }else{
                //kintone async/await による非同期処理(成功イベントREST API処理時)：
                async function updateRecord(fieldCode:string,event:any) {
                    return new Promise((resolve, reject) => {
                        var updatedRecord = {
                            app: event.appId,
                            id:  event.recordId,
                            record: {[fieldCode]:{"value":saveValue}}
                        };
                        kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', updatedRecord, (resp) => {
                            resolve(resp);
                        }, (error) => {
                            reject(error);
                        });
                    });
                }
                //kintone保存先フィールド存在確認：
                record[this.props.saveField.code].value=saveValue;
                //kintone async/await による非同期処理：
                await updateRecord(this.props.saveField.code,event);   
                //一覧画面更新成功後手動リロードください：                      
                if (event.type.includes('index')){
                    //window.alert("文字結合行いました。"+this.props.joinField1.name+":"+joinValue1+","+this.props.joinField2.name+":"+joinValue2+"。一覧画面更新成功後自動リロードしません。必要に応じて手動リロードください。");
                    window.alert("文字結合には、一覧画面更新成功後自動リロードしません。必要に応じて手動リロードください。");
                }
            }
//////////////////////////////////////////////////////////////////////////////////////////////////////
            result= {
                canNext:true,
                result:true
            }
            return result;
        }catch(error){;
            if (event.type.includes('success')){
                window.alert("[windows alert]：処理中異常が発生しました。結合しません。システム担当者へお問合せください。errorメッセージ："+error)
            }
            event.error="[エラーメッセージ]：処理中異常が発生しました。結合しません。システム担当者へお問合せください。errorメッセージ："+error;
            return {
                canNext:false,
                result:false
            }
        }
    }
///////////////////////////////////////////////////////////////////////////////////////////////
    register(): void {
        actionAddins[this.name]=this;
    }
}
new StringJoinAction();