

import { each } from "jquery";
import { actionAddins } from ".";
import {  IAction,IActionResult, IActionNode, IActionProperty, IField, IContext } from "../types/ActionTypes";
import { ConditionTree } from '../types/Conditions';



/**
 * アクションの属性定義
 */
interface IInsertValueProps{
    field:IField;
    condition:string;
    value:string;
    show:string;
}
/**
 *
 */
export class InsertValueAction implements IAction{
    name: string;
    actionProps: IActionProperty[];
    props:IInsertValueProps;
    constructor(){
        this.name="値を挿入する";// DBに登録したアクション名
        this.actionProps=[];
        //プロパティ属性の初期化
        this.props={
            field:{code:''},
            condition:'',
            value:'',
            show:''
        }
        //アクションを登録する
        this.register();
    }

    /**
     * 空白文字を空白文字が非対応のフィールドに挿入しようとしていないか、必須項目フィールドに挿入しようとしていないかチェックする
     * @param {string} inputValue - 挿入する値
     * @return {boolean} -入力値が有効な日付形式の場合はtrueを返し、そうでない場合は例外を発生させる
     */
    checkInputValueBlank(fieldType :string | undefined,inputValue :string,fieldCode :string,fieldRequired :boolean | undefined,event :any): boolean{

        let valueHasBlank;
        //正規表現チェック
        valueHasBlank = inputValue.match(/^(\s|　)*$/);//値が半角スペース・タブ文字・改行・改ページ・全角スペースのみであるか


        //値に空白文字が入っている、nullのときは、エラーチェックする
        if(valueHasBlank !== null || inputValue === null || inputValue === ''){
            //空白文字を空白文字が非対応のフィールドに挿入しようとしている場合、例外を発生させる
            if(fieldType === "NUMBER" || fieldType === "DATE" || fieldType === "DATETIME" || fieldType === "TIME" || fieldType === "USER_SELECT"
                        || fieldType === "ORGANIZATION_SELECT" || fieldType === "GROUP_SELECT" || fieldType === "RADIO_BUTTON" || fieldType === "DROP_DOWN" || fieldType === "CHECK_BOX" || fieldType === "MULTI_SELECT"){
                event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"に挿入しようとした、値は空白文字です。"; //レコードにエラーを表示
                throw new Error("「"+fieldCode+"」"+"に挿入しようとした、値は空白文字です。「値を挿入する」コンポーネントの処理を中断しました。");

            //空白文字を必須項目フィールドに挿入しようとしている場合、例外を発生させる
            }else if(fieldRequired){
                event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドは必須項目のため、空白文字は挿入できません。"; //レコードにエラーを表示
                throw new Error("「"+fieldCode+"」"+"フィールドは必須項目のため、空白文字は挿入できません。「値を挿入する」コンポーネントの処理を中断しました。");
            }
        }

        return true;
    }

    /**
     * 空白文字の変数を非対応のフィールドに挿入しようとしていないか、必須項目フィールドに挿入しようとしていないかチェックする
     * @param {string} inputValue - 挿入する値
     * @return {boolean} -入力値が有効な日付形式の場合はtrueを返し、そうでない場合は例外を発生させる
     */
    checkVariableValueBlank(fieldType :string | undefined,inputValueArray :any,fieldCode :string,fieldRequired :boolean | undefined,event :any): boolean{

        let variableHasBlank;
        //正規表現チェック
        for(let i =0;i<inputValueArray.length;i++){
            //配列の要素にnullがないか、空白文字が値に含まれていないかチェックする
            if (typeof inputValueArray[i] === "string"){
            variableHasBlank = inputValueArray[i].match(/^(\s|　)*$/);//値が半角スペース・タブ文字・改行・改ページ・全角スペースのみであるか
            }
        }

        //変数の値に空白文字が入っている、配列に要素がないときは、エラーチェックする
        if(variableHasBlank !== null && variableHasBlank !== undefined &&  variableHasBlank !== "" && inputValueArray.length === 0){
            //空白文字を空白文字が非対応のフィールドに挿入しようとしている場合、例外を発生させる
            if(fieldType === "NUMBER" || fieldType === "DATE" || fieldType === "DATETIME" || fieldType === "TIME" || fieldType === "USER_SELECT"
                || fieldType === "ORGANIZATION_SELECT" || fieldType === "GROUP_SELECT" || fieldType === "RADIO_BUTTON" || fieldType === "DROP_DOWN" || fieldType === "CHECK_BOX" || fieldType === "MULTI_SELECT"){
                event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"に挿入しようとした、変数の値は空白文字です。"; //レコードにエラーを表示
                throw new Error("「"+fieldCode+"」"+"に挿入しようとした、変数の値は空白文字です。「値を挿入する」コンポーネントの処理を中断しました。");

            //空白文字を必須項目フィールドに挿入しようとしている場合、例外を発生させる
            }else if(fieldRequired){
                event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドは必須項目であり、空白・空白文字の値の変数は、挿入できません。"; //レコードにエラーを表示
                throw new Error("「"+fieldCode+"」"+"フィールドは必須項目であり、空白・空白文字の値の変数は、挿入できません。「値を挿入する」コンポーネントの処理を中断しました。");
            }
        }

        return true;
    }

    /**
     * 入力値が半角数字かチェックする関数
     * @param {string} inputValue - 挿入する値
     * @return {boolean} -入力値が有効な数値の場合はtrueを返し、そうでない場合は例外を発生させる
     */
    checkInputNumber(inputValue :string,fieldCode :string,event :any): boolean{
        let inputNumberValue = Number(inputValue);//数値型に変換

        //有限数かどうか判定
        if(!isFinite(inputNumberValue)){
            event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。"; //レコードにエラーを表示
            throw new Error("「"+fieldCode+"」"+"フィールドに入れようとした値は、有効な数値ではありません。「値を挿入する」コンポーネントの処理を中断しました。");
        }
        return true;
    }

    /** 入力値が有効な日付形式かチェックする関数
     * @param {string} inputValue - 挿入する値
     * @return {boolean} -入力値が有効な日付形式の場合はtrueを返し、そうでない場合は例外を発生させる
     */
    checkInputDate(inputValue :string,fieldCode :string,event :any): boolean{
        //正規表現チェック
        let twoDigitMonthDay = inputValue.match(/(\d{4})-(\d{2})-(\d{2})$/);//4桁の数字-2桁の数字-2桁の数字
        let singleDigitMonthDay = inputValue.match(/(\d{4})-(\d{1})-(\d{1})$/);//4桁の数字-1桁の数字-2桁の数字
        let singleDigitMonth = inputValue.match(/(\d{4})-(\d{1})-(\d{2})$/);//4桁の数字-1桁の数字-2桁の数字
        let singleDigitDay = inputValue.match(/(\d{4})-(\d{2})-(\d{1})$/);//4桁の数字-2桁の数字-1桁の数字
        let dateTimeMilliSecond = inputValue.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}).(\d{2,3})Z$/);//時刻入りのUTCの日付形式(ミリ秒)
        let dateTime = inputValue.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/);//時刻入りのUTCの日付形式
        let date;
        //date型に変換
        date = new Date(inputValue);

        //date型変換できたか確認
        if(date !== undefined && !isNaN(date.getDate())){
            //正規表現チェック確認
            if(twoDigitMonthDay === null && singleDigitMonth === null && singleDigitDay === null && singleDigitMonthDay === null && dateTime === null && dateTimeMilliSecond === null){
                    event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。"; //レコードにエラーを表示
                    throw new Error("「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。「値を挿入する」コンポーネントの処理を中断しました。");
            }
        }
        return true;
    }

    /** 入力値が有効な時刻形式かチェックする関数
     * @param {string} inputValue - 挿入する値
     * @return {boolean} -入力値が有効な日付形式の場合はtrueを返し、そうでない場合は例外を発生させる
     */
    checkInputTime(inputValue :string,fieldCode :string,event :any): boolean{
        //正規表現チェック
        let timeFormat =inputValue.match(/^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/);

        //正規表現チェック確認
        if(timeFormat === null){
            event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な時刻形式です。"; //レコードにエラーを表示
            throw new Error("「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な時刻形式です。「値を挿入する」コンポーネントの処理を中断しました。「1～2桁 : 2桁」の値を指定してください。");
        }
        return true;
    }

    /**
     * 入力値のフィールドタイプがDATETIMEであれば、時刻ありの日付形式変換し、DATEであれば時刻なしの日付形式変換する関数
     * @param {string} inputValue -挿入する値
     * @param {string} fieldType  -フィールドタイプ
     * @return {string} -入力値が日付形式に変換できた場合は文字列を返し、そうでない場合は例外を発生させる
     */
    changeDateFormat(inputValue :string, fieldType :string,fieldCode :string,event :any): string{
        let dateTime;
        let date;

        //挿入する値をdate型に変換
        date = new Date(inputValue);
        //date型変換できたか確認
        if(date !== undefined && !isNaN(date.getDate())){

            //日時フィールドの場合、時刻ありの日付形式変換
            if(fieldType === "DATETIME"){
                dateTime =date.toISOString();
                return dateTime;
            }

            //日付フィールドの場合、時刻なしの日付に形式変換
            //UTCの時刻を挿入したい場合、JSTに変換する
            let dateTimeMilliSecond = inputValue.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}).(\d{2,3})Z$/);//時刻入りのUTCの日付形式(ミリ秒)
            let dateTimeNotIncludingMilliSeconds = inputValue.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/);//時刻入りのUTCの日付形式

            if(dateTimeMilliSecond !== null || dateTimeNotIncludingMilliSeconds !== null){
                //JSTに変換
                let jstDate=date.toLocaleString("ja-JP", { timeZone: "Asia/Tokyo" });
                console.log(jstDate);
                let dateArray=jstDate.match(/(\d{4})\/(\d{1,2})\/(\d{1,2})/);//4桁の数字-1～2桁の数字-1～2桁の数字
                if(dateArray !== null){
                    let yearIndex = 1;
                    let monthIndex = 2;
                    let dayIndex = 3;
                    let dateFormatted=`${dateArray[yearIndex]}-${dateArray[monthIndex]}-${dateArray[dayIndex]}`
                    return dateFormatted;
                }
            }

            //UTC時刻でない値を挿入したい場合、年、月、日を抽出し、月-年-日の形式変換
            let dateArray=inputValue.match(/(\d{4})-(\d{1,2})-(\d{1,2})$/);//4桁の数字-1～2桁の数字-1～2桁の数字
            if(dateArray !== null){
                let yearIndex = 1;
                let monthIndex = 2;
                let dayIndex = 3;
                let dateFormatted=`${dateArray[yearIndex]}-${dateArray[monthIndex]}-${dateArray[dayIndex]}`
                return dateFormatted;
            }

        }

        event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。"; //レコードにエラーを表示
        throw new Error("「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。「値を挿入する」コンポーネントの処理を中断しました。");
    }

    /**
     * 入力値がフィールドタイプ(ラジオボタン・ドロップダウン・複数選択・ドロップダウン)の選択肢に存在する値かチェックする関数
     * @param {string} inputValue - 挿入する値
     * @return {boolean} -入力値が有効な値の場合はtrueを返し、そうでない場合は例外を発生させる
     */
    checkInputOption(inputValue :string,fieldOptions :string | undefined,fieldCode :string,event :any): boolean {

        //入力値が選択肢に存在する値かチェックし、存在したらtrueを返す
        if(fieldOptions !== undefined){
            let options = Object.keys(fieldOptions);
            for(var optionsIndex in options){
                if(options[optionsIndex] === inputValue){
                    return true;
                }
            }
        }

        event.record[fieldCode]['error']="「"+fieldCode+"」"+"には、存在しない値を挿入しようとしたため、処理を中断しました。";
        throw new Error("「"+fieldCode+"」"+"には、存在しない値を挿入しようとしたため、処理を中断しました。「値を挿入する」コンポーネントの処理を中断しました。");
    }

    /**
     * 入力値がフィールドタイプ(ユーザー選択)で、ユーザー情報に存在する値かチェックする関数
     * @param {string} inputValue - 挿入する値
     * @return {string | boolean} 入力値が登録されているユーザー情報から見つかった場合、trueを返し、見つからなかった場合、falseを返す
     */
    async setInputUser(inputValue :any): Promise<any | boolean>{

        //ユーザー名を格納する変数
        let usersName = [];

        try{
            //APIでユーザー情報を取得する
            const resp =await kintone.api(kintone.api.url('/v1/users', true), 'GET', {codes: inputValue.join(',')})
            let usersInfo = resp.users;

            if (usersInfo.length !== inputValue.length) {
                throw new Error();
            }

            //入力されたログイン名がユーザー情報に登録されている場合、そのユーザー名を取得する
            for (let indexUsersInfo in usersInfo) {
                for(let indexInputUser in inputValue){
                    if(usersInfo[indexUsersInfo].code === inputValue[indexInputUser]){
                        usersName.push(usersInfo[indexUsersInfo].name);
                    }
                }
            }

            //ユーザー名が取得できた場合、ログイン名とユーザー名をフィールドにセットする
            if(usersName === undefined){
                throw new Error();
            }
        }catch{
            return false;
        }
        return usersName;
    }

    /**
     * 入力値がフィールドタイプ(組織選択)で、組織情報に存在する値かチェックする関数
     * @param {string} inputValue - 挿入する値
     * @return {string | boolean} 入力値が登録されている組織情報から見つかった場合、trueを返し、見つからなかった場合、falseを返す
     */
    async setInputOrganization(inputValue :string): Promise<string | boolean>{

        //組織名を格納する変数
        let organizationName;
        const organizationsInfoColumnIndex=0;

        try{
            //APIで組織情報を取得する
            const resp =await kintone.api(kintone.api.url('/v1/organizations.json', true), 'GET', {codes:[inputValue ]})

            //入力された組織コードが組織情報に登録されている場合、その組織名を取得する
                if (resp.organizations[organizationsInfoColumnIndex].code === inputValue) {
                    organizationName=resp.organizations[organizationsInfoColumnIndex].name;
                }

            //組織名が取得できた場合、組織コードと組織名をフィールドにセットする
            if(organizationName === undefined){
                throw new Error();
            }
        }catch{
            return false;
        }

        return organizationName;
    }

    /**
     * 入力値がフィールドタイプ(グループ選択)で、グループ情報に存在する値かチェックする関数
     * @param {string} inputValue - 挿入する値
     * @return {string | boolean} 入力値が登録されているグループ情報から見つかった場合、trueを返し、見つからなかった場合、falseを返す
     */
    async setInputGroup(inputValue :string): Promise<string | boolean>{

        //グループ名を格納する変数
        let groupsName;
        const groupsInfoColumnIndex=0;

        try{
            //APIでグループ情報を取得する
            const resp =await kintone.api(kintone.api.url('/v1/groups.json', true), 'GET', {codes:[inputValue ]})

            //入力されたグループコードがグループ情報に登録されている場合、そのグループ名を取得する
            if (resp.groups[groupsInfoColumnIndex].code === inputValue) {
                groupsName=resp.groups[groupsInfoColumnIndex].name;
            }

            //グループ名が取得できた場合、グループコードとグループ名をフィールドにセットする
            if(groupsName === undefined){
                throw new Error();
            }
        }catch{
            return false;
        }

        return groupsName;
    }

    /**
     * ユーザーオブジェクトを挿入する場合、挿入先フィールドによって、適切なオブジェクトの値を取得し、セットする
     * @param {string} inputValue -入力された値
     * @param {string} objectValue -オブジェクト変数
     * @param {string} fieldType -挿入先フィールドタイプ
     * @param {string} fieldCode -挿入先フィールドタイプ
     * @return {string} -挿入先フィールドによって、ログインユーザーオブジェクトの何の値を返すか、変わる
     */
    setValueOfUserObject(inputValue :any,objectValue :any,fieldType : any,fieldCode : any): any{

        //変数の値
        let variableValue = [];

        //ユーザーオブジェクト挿入できないフィールド（日付、数値）を選択している場合、エラーを出す
        if(fieldType === "NUMBER" || fieldType === "DATE" || fieldType === "DATETIME" || fieldType === "TIME"){
            throw new Error("「"+fieldCode+"」"+"フィールドには、ユーザー情報を挿入できません。処理を中断しました。");
        }

        //ユーザー選択フィールドに挿入時、ユーザーオブジェクトのcodeを代入する
        if(fieldType === 'USER_SELECT'){
            //変数の値取得
            if(!Array.isArray(objectValue)){
                variableValue.push(objectValue.code);
            }else{
                for(let i=0;i<objectValue.length;i++){
                    variableValue.push(objectValue[i].code);
                }
            }

        }else{
            //ユーザー選択フィールド以外に挿入時、ユーザーオブジェクトの値の指定があれば、その値を代入する
            if(inputValue.includes('.name') || inputValue.includes('.email') || inputValue.includes('.employeeNumber')
                || inputValue.includes('.extensionNumber') || inputValue.includes('.id') || inputValue.includes('.isGuest')|| inputValue.includes('.timezone')
                || inputValue.includes('.language') || inputValue.includes('.mobilePhone') || inputValue.includes('.phone') || inputValue.includes('.url')){

                //値を挿入する変数名取得
                let objectPropertyName = inputValue.split('.')[1];
                if(!Array.isArray(objectValue)){
                    variableValue.push(objectValue[objectPropertyName]);
                }else{
                    for(let i=0;i<objectValue.length;i++){
                        variableValue.push(objectValue[i][objectPropertyName]);
                    }
                }

            //ユーザー選択フィールド以外に挿入時、ユーザーオブジェクトの値の指定がなければ、codeを代入する
            }else{
                if(!Array.isArray(objectValue)){
                    variableValue.push(objectValue.code);
                }else{
                    for(let i=0;i<objectValue.length;i++){
                        variableValue.push(objectValue[i].code);
                    }
                }
            }
        }

        if(variableValue === undefined){
            throw new Error("「"+fieldCode+"」"+"フィールドに入れようとした変数は、無効な入力形式です。");
        }

        return variableValue;
    }



    /**
     * アクションの実行を呼び出す
     * @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) && !('value' in actionNode.ActionValue)) {
                return result
            }

            const fieldColumnIndex=1;

            //プロパティで選択されたフィールド
            const field=this.actionProps[fieldColumnIndex].props.modelValue.type;

            //プロパティの値を挿入するフィールドが未選択の場合、例外を発生させる
            if(field === null){
                throw new Error("「値を挿入する」コンポーネントで、値を挿入するフィールドが指定されていなかったため、処理が中断されました。");
            }

            //プロパティの値を挿入するフィールドが非対応フィールドの場合、例外を発生させる
            //添付ファイル・テーブル・カテゴリー・ステータス・作成者・更新者・作業者・リビジョン番号・レコード番号・レコードID・計算・作成日時・更新日時フィールドが選択されている場合、例外を発生させる
            if(field === "FILE" || field === "SUBTABLE" || field === "CATEGORY" || field === "STATUS"
                    || field === "STATUS_ASSIGNEE" || field === "CREATOR" || field === "MODIFIER" || field === "__REVISION__"
                        || field === "RECORD_NUMBER"|| field === "__ID__" || field ==="CALC" || field === "CREATED_TIME" || field === "UPDATED_TIME" ){
                throw new Error("「値を挿入する」コンポーネントで、選択されたフィールドは、値を挿入するコンポーネントでは非対応のフィールドのため、処理を中断しました。");
            }

            //既定のプロパティのインターフェースへ変換する
            this.props = actionNode.ActionValue as IInsertValueProps;

            //プロパティの挿入する値を取得
            let fieldValue = this.props.value;
            //フィールドの種類を取得
            const fieldType = this.props.field.type;
            //フィールドが必須項目なのか取得
            const fieldRequired=this.props.field.required;
            //挿入するフィールドのコードを取得
            const fieldCode=this.props.field.code;
            //挿入する値の形式（手入力か変数）を取得
            const insertValueType=this.props.show;
            //ラジオボタン・チェックボックス・複数選択・ドロップダウンの選択肢を取得
            let fieldOptions =this.props.field.options;
            //変数の値を格納する
            let variableValue :any;
            //挿入する値を格納する
            let fieldValueArray = [];
            let notInputError;
            //contextに存在する変数名を格納する
            let contextHasVariablesNames;

            //変数の場合、値が取得できるかチェック
            if(insertValueType === "変数"){

                //変数の値を呼び出して代入する
                const getContextVarByPath = (obj: any, path: string) => {
                    return path.split(".").reduce((o, k) => (o || {})[k], obj);
                };

                //contextに存在する変数名を全て取得する
                contextHasVariablesNames = Object.keys(context.variables);
                //contextに変数が1つも存在しない場合、エラーを出す
                if(contextHasVariablesNames.length === 0){
                    throw new Error("「"+fieldCode+"」"+"フィールドに挿入しようとした変数は、存在しないため、処理を中断しました。");
                }

                let inputVariablesName;
                //入力値がオブジェクト変数の変数名であり、プロパティの指定がある場合、変数名のみ取得
                if (fieldValue.includes('.')) {
                    // '.'より前の文字を抽出
                    inputVariablesName = fieldValue.split('.')[0];
                } else {
                    // '.'が含まれていない場合、そのまま返す
                    inputVariablesName = fieldValue;
                }

                let inputVariablesExist;
                //入力された変数名が、contextの変数に存在する場合、inputVariablesExistにtrueに代入する
                for(let i=0;i< contextHasVariablesNames.length;i++){
                    if(inputVariablesName === contextHasVariablesNames[i]){
                        inputVariablesExist = true;
                    }
                }

                //入力された変数名が、contextの変数に存在しない場合、エラーを表示する
                if(!inputVariablesExist){
                    throw new Error("「"+fieldCode+"」"+"フィールドに挿入しようとした変数は、存在しないため、処理を中断しました。");
                }

                if(inputVariablesName){
                    //入力された変数名の値を取得
                    variableValue = getContextVarByPath(context.variables,inputVariablesName)
                }

                //文字列型のフィールド以外に、空白文字の変数の値を挿入する場合、エラーを出す
                if(variableValue === "" || variableValue === null){
                    if(fieldType === "NUMBER" || fieldType === "DATE" || fieldType === "DATETIME" || fieldType === "TIME" || fieldType === "USER_SELECT"
                        || fieldType === "ORGANIZATION_SELECT" || fieldType === "GROUP_SELECT" || fieldType === "RADIO_BUTTON" || fieldType === "DROP_DOWN" || fieldType === "CHECK_BOX" || fieldType === "MULTI_SELECT"){
                        throw new Error("「"+fieldCode+"」"+"フィールドに挿入しようとした変数は、値がnullのため、処理を中断しました。");
                    }
                }


                //変数がオブジェクトの場合、プロパティを取得し、何のオブジェクトか判断する
                if(typeof variableValue === 'object'){
                    let objectProperties=[]

                    if(variableValue.length > 0){
                        objectProperties=Object.keys(variableValue[0]);
                    }else{
                        objectProperties = Object.keys(variableValue);
                    }

                    //(ログインユーザー・値取得のコンポーネントからの)ユーザーオブジェクトを挿入時、挿入先フィールドによって、値を指定する
                    if(objectProperties.includes('code') && objectProperties.includes('name')){
                        variableValue=this.setValueOfUserObject(fieldValue,variableValue,fieldType,fieldCode);

                        //ユーザーオブジェクトから取得した値を、fieldValueArrayに代入
                        for (const value of variableValue) {
                            fieldValueArray.push(value);
                        }
                    }
                }else{
                    //オブジェクト変数でない場合、変数をfieldValueArrayに代入
                    variableValue = context.variables[fieldValue]
                    fieldValueArray[0] = variableValue;
                }

                //変数がfieldValueArrayに代入できなかった場合、エラーを出す
                if(fieldValueArray === undefined){
                    throw new Error("「"+fieldCode+"」"+"フィールドに入れようとした変数は、無効な入力形式です。");
                }

                //変数の値にエラー（空文字・空白文字の混入）がないことをチェックする
                notInputError=this.checkVariableValueBlank(fieldType,fieldValueArray,fieldCode,fieldRequired,event);

            //手入力の値を挿入する場合、挿入する値をfieldArrayに代入
            }else{
                fieldValueArray.push(fieldValue);
                //入力エラー（空白文字の混入）がないことをチェック
                notInputError=this.checkInputValueBlank(fieldType,fieldValue,fieldCode,fieldRequired,event);
            }

            //形式変換、型変換した値を格納する変数
            let correctFormattedValue = undefined;
            //形式変換、型変換した値を格納する配列
            let correctValues :any[] = [];

            //条件式の結果がtrue、入力エラー（空白文字の混入）がない場合、挿入する値をフィールドタイプ別にチェックする
            if(notInputError){

                //文字列型のフィールドに挿入しようとしている値が適切の場合、correctFormattedValueに代入する
                if(fieldType === "SINGLE_LINE_TEXT" || fieldType === "MULTI_LINE_TEXT" || fieldType === "RICH_TEXT" || fieldType === "LINK" ){
                    correctFormattedValue = fieldValueArray.join(',');

                //数値型のフィールドに挿入しようとしている値が適切の場合、数値型に型変換してcorrectFormattedValueに代入する
                }else if(fieldType === "NUMBER" ){
                    if(this.checkInputNumber(fieldValueArray[0],fieldCode,event)){//入力値チェック
                        correctFormattedValue = Number(fieldValueArray[0]);//型変換
                    }

                //日付・日時型のフィールドに挿入しようとしている値が適切の場合、指定の日付・日時に形式変換してcorrectFormattedValueに代入する
                }else if(fieldType === "DATE" || fieldType === "DATETIME" ){
                    if(this.checkInputDate(fieldValueArray[0],fieldCode,event)){//入力値チェック
                        let formattedDate = this.changeDateFormat(fieldValueArray[0],fieldType,fieldCode,event)
                        if(formattedDate){
                            correctFormattedValue = formattedDate
                        }
                    }

                //時刻フィールドに挿入しようとしている値が適切の場合、correctFormattedValueに代入する
                }else if(fieldType === "TIME"){
                    if(this.checkInputTime(fieldValueArray[0],fieldCode,event)){//入力値チェック
                        correctFormattedValue = fieldValueArray[0];
                    }

                //ラジオボタン・ドロップダウンのフィールドの選択肢と入力値が一致した場合、correctFormattedValueに代入する
                }else if(fieldType === "RADIO_BUTTON" || fieldType === "DROP_DOWN"){
                    if(this.checkInputOption(fieldValueArray[0],fieldOptions,fieldCode,event)){//入力値チェック
                        correctFormattedValue = fieldValueArray[0];
                    }

                //チェックボックス・複数選択のフィールドの選択肢と入力値が一致した場合、correctValuesの配列に代入する
                }else if(fieldType === "CHECK_BOX" || fieldType === "MULTI_SELECT" ){
                    if(this.checkInputOption(fieldValueArray[0],fieldOptions,fieldCode,event)){//入力値チェック
                        correctValues[0] = fieldValueArray[0];
                    }

                //ユーザー情報フィードに挿入しようとした値が適切な場合、correctValues(配列)に代入する
                }else if(fieldType === "USER_SELECT"){
                    //挿入する値がユーザー情報から見つかれば、ユーザー名を格納
                    let usersName=await this.setInputUser(fieldValueArray);

                    //ユーザー名が格納できている場合、ログイン名とユーザー名をcorrectValues（配列）に代入する
                    if(!usersName){
                        event.record[fieldCode]['error']="ユーザー選択に、挿入しようとしたユーザー情報は見つかりませんでした。「値を挿入する」コンポーネントの処理を中断しました。";
                        throw new Error("ユーザー選択に、挿入しようとしたユーザー情報は見つかりませんでした。「値を挿入する」コンポーネントの処理を中断しました。");
                    }

                    for(let indexInputUser in fieldValueArray){
                        correctValues.push({ code: fieldValueArray[indexInputUser], name: usersName[indexInputUser] });
                    }

                //組織情報フィードに挿入しようとした値が適切な場合、correctFormattedValueに代入する
                }else if(fieldType === "ORGANIZATION_SELECT"){
                    //挿入する値が組織情報から見つかれば、組織名を格納
                    let organizations=await this.setInputOrganization(fieldValue);

                    //組織名が格納できている場合、組織コードと組織名をcorrectFormattedValueに代入する
                    if(!organizations){
                        event.record[fieldCode]['error']="組織選択フィールドに、挿入しようとした組織情報は見つかりませんでした。「値を挿入する」コンポーネントの処理を中断しました。";
                        throw new Error("組織選択フィールドに、挿入しようとした組織情報は見つかりませんでした。「値を挿入する」コンポーネントの処理を中断しました。");
                    }else{
                        correctFormattedValue=[{ code: fieldValue, name: organizations}];
                    }

                //グループ情報フィードに挿入しようとした値が適切な場合、correctFormattedValueに代入する
                }else if(fieldType === "GROUP_SELECT"){
                    //挿入する値がグループ情報から見つかれば、グループ名を格納
                    let groups=await this.setInputGroup(fieldValue);

                    //グループ名が格納できている場合、グループコードとグループ名をcorrectFormattedValueに代入する
                    if(!groups){
                        event.record[fieldCode]['error']="グループ選択フィールドに、挿入しようとしたグループ情報は見つかりませんでした。「値を挿入する」コンポーネントの処理を中断しました。";
                        throw new Error("グループ選択フィールドに、挿入しようとしたグループ情報は見つかりませんでした。「値を挿入する」コンポーネントの処理を中断しました。");
                    }else{
                        correctFormattedValue=[{ code: fieldValue, name: groups}];
                    }
                }
            }

            const conditionResult = this.getConditionResult(context);
            //保存成功イベントの場合、kintone async/await による非同期処理でフィールドに値を挿入する
            if(!event.type?.includes('success')){

                //条件式の結果がtrueかつ挿入する値が変換できた場合、フィールド（ラジオボタン・ドロップダウン・チェックボックス・複数選択・文字列一行・文字列複数行・リッチエディタ・数値・日付・日時・時刻）にセット
                if(conditionResult){
                    //値を正しい形式に変換できた場合、フィールドに値をセットする
                    if(correctFormattedValue !== undefined){
                        event.record[fieldCode].value = correctFormattedValue;
                    //値を正しい形式（配列）に変換できた場合、フィールドに値（配列）をセットする
                    }else{
                        event.record[fieldCode].value = correctValues;
                    }
                }

            }else{

                //挿入する値を挿入先フィールドに値をセットし、kintoneAPIによってレコード更新を行う
                async function setUpdateData(conditionResult:boolean,fieldCode:string,event:any,correctFormattedValue :any,correctValues :any) {

                    //値を正しい形式に変換できた場合、フィールドに値をセットする
                    if(correctFormattedValue !== undefined){
                        event.record[fieldCode].value = correctFormattedValue;
                    //値を正しい形式（配列）に変換できた場合、フィールドに値（配列）をセットする
                    }else{
                        event.record[fieldCode].value = correctValues;
                    }

                    // 条件が真の場合の処理、kintoneAPIによる非同期処理（レコード更新）
                    if(conditionResult){
                        if(correctFormattedValue !== undefined){
                            await updateData(fieldCode,event,correctFormattedValue);
                        }else{
                            await updateData(fieldCode,event,correctValues);
                        }
                    }
                }

                //kintone async/await による非同期処理（レコード更新）
                async function updateData(fieldCode:string,event:any,insertValue:any) {
                    try{
                        var updatedRecord = {
                            app: event.appId,
                            id:  event.recordId,
                            record: {[fieldCode]:{"value":insertValue}}
                        };
                        //APIでユーザー情報を取得する
                        const resp =await kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', updatedRecord)

                    }catch{
                        return false;
                    }
                }

                // 関数の呼び出し
                setUpdateData(conditionResult,fieldCode,event,correctFormattedValue,correctValues);

            };

            result= {
                canNext:true,
                result:true
            }
            return result;
        }catch(error:any){
            context.errors.handleError(error,actionNode);
            result.canNext=true;//次のノードは処理を続ける
            return result;
        }
    }

    /**
     *
     * @param context 条件式を実行する
     * @returns
     */
    getConditionResult(context:any):boolean{
        //プロパティ`condition`から条件ツリーを取得する
        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 InsertValueAction();