const ITEM_ID = 'item_id';
const schemaParam = '&schema=' + $('#schema').val();
const apiUrlBase = $('#api_url_base').val();
const breadcrumbsUniqueNum = Math.floor(Date.now()/10800000).toString();

// クリックイベント時に実行する関数
const clickEvent = ({
    setEventListener: function ( {sourceDataLayerEventName, eventType, targetElement} ) {
        const pathName = commonEvent.getUrlPathName();
        switch(pathName) {
            case 'cart': {
                
                // カート画面で発生するイベント

                // add_payment_info 支払い情報を送信したとき => /order/completeへ統合

                // add_shipping_info 配送先情報を送信したとき => /order/completeへ統合

                // remove_from_cart カートから削除 => $().removeCommodity()処理内へ結合
                break;
            }
            case 'category':
            case 'brand':
            case 'favorite-brand':
            case 'in-shop':
            case 'search': {
                // 商品一覧から商品をクリックするイベント
                const targetCommodityElements = this.getTargetElements(targetElement.selectItem);
                if (targetCommodityElements !== null) {
                    this.addClickEvent(targetCommodityElements, sourceDataLayerEventName, null, eventType);
                };
                break;
            }
            case 'commodity': {
                
                // // カートに入れるイベント => jquery.commodity-pc.js へ統合

                // お気に入り登録するイベント $(this).addFavorite('{${detail.skuCode}}')へ結合

                break;
            }
            case 'other': {
                // その他
                break;
            }
            default: {
                return false;
            }
        };
    },
    getTargetElements: function (targetElement) {
        if (document.querySelectorAll(targetElement).length > 0) {
            return document.querySelectorAll(targetElement);
        } else {
            return null
        };
    },
    addClickEvent: function (targetArray, sourceDataLayerEventName, commodityCode, eventType) {
        switch(eventType) {
            case 'add_to_cart': {
                targetArray.forEach((target) => {
                    target.addEventListener('click', (target)=> {
                        const skuCode = $(target)[0].currentTarget.dataset.skuCode;
                        const sizeLabel = $(target)[0].currentTarget.dataset.sizeLabel;
                        this.addToCart(commodityCode, sourceDataLayerEventName, skuCode, sizeLabel);
                    });
                });
                return true;
            }
            case 'select_item': {
                targetArray.forEach((target) => {
                    target.addEventListener('click', (target)=> {
                        if(commodityCode !== null) {
                            this.selectItem(commodityCode, sourceDataLayerEventName);
                        } else {
                            const commodityCode = $($(target)[0].currentTarget).find('[data-skucode]').data('skucode');
                            if (commodityCode.length === 0) return; 
                            this.selectItem(commodityCode, sourceDataLayerEventName);
                        }
                    });
                });
                return true;
            }
            default: 
                return false;
        }
    },
    removeFromCart: function (sku, sourceDataLayerEventName) {
        // dataLayerからソース元イベントのobjを探す
        const data = window.dataLayer || null;
        const viewItemData = data.filter((data, index, array) => {
            if(array[index].event == sourceDataLayerEventName) return data;
        });

        // 指定イベントがない場合(クリックイベントとdataLayerが異なる場合)
        if (viewItemData.length === 0) return false;

        // 該当objのitemsデータを配列で取得する
        // itemsの中からクリックした商品コードで詳細情報を取得する
        const clickItem = viewItemData[0].ecommerce.items.filter((item) => {
            if(item.item_id === sku.slice(0, -3) && item.item_variant === sku.slice(-3) ) return item;
        });

        // dataLayer内に指定の商品IDが取得できなかった場合
        if (clickItem.length === 0) return false

        // クリックeventデータのobj生成し、itemsデータを結合
        const initClickData = {
          event: 'remove_from_cart',
          ecommerce: {
            value: clickItem[0].price,
            currency: 'JPY',
            items: clickItem
          }
        };
        
        // データレイヤーへセット
        this.pushDataLayer(initClickData);

    },
    addBuylater: function (sku) {
        // dataLayerからソース元イベントのobjを探す
        const data = window.dataLayer || null;

        // クリックeventデータのobj生成し、itemsデータを結合
        const initClickData = {
          event: 'add_buylater',
          commodity_code: sku.slice(0, -3)
        };
        
        // データレイヤーへセット
        this.pushDataLayer(initClickData);

    },
    addToCart: function (commodityCode, sourceDataLayerEventName, skuCode, sizeLabel, colorName, supplierCode, janCode ) {
        if (typeof commodityCode === 'undefined' || commodityCode === null) return;

        // dataLayerから指定イベントのobjを探す
        const data = window.dataLayer || null;
        const viewItemData = data.filter((data, index, array) => {
            if(array[index].event == sourceDataLayerEventName) return data;
        });

        // 指定イベントがない場合(クリックイベントとdataLayerが異なる場合)
        if (viewItemData.length === 0) return false;

        // 該当objのitemsデータを取得する
        let clickItem = viewItemData[0].ecommerce.items.filter((data, index, array) => {
            if(array[index].item_id == commodityCode) return data;
        });

        // dataLayer内に指定の商品IDが取得できなかった場合
        if (clickItem.length === 0) clickItem = setDefcolorCommodityData(skuCode, viewItemData[0].ecommerce.items);

        // 属性"data-xxx"から値をセット
        // 当該ページならこのまま、違う色ならスキップしたい★
        if (typeof skuCode !== 'undefined' && clickItem.length !== 0) clickItem[0].item_variant = skuCode.slice(-3);
        if (typeof skuCode !== 'undefined' && clickItem.length !== 0) clickItem[0].item_sizesku = skuCode;

        if (typeof sizeLabel !== 'undefined' && clickItem.length !== 0) clickItem[0].item_sizeLabel = sizeLabel;
        if (typeof colorName !== 'undefined' && clickItem.length !== 0) clickItem[0].item_colorName = colorName;
        // if (typeof supplierCode !== 'undefined' && clickItem.length !== 0) clickItem[0].makerID = supplierCode;
        if (typeof janCode !== 'undefined' && clickItem.length !== 0) clickItem[0].janCode = janCode;

        
        // クリックeventデータのobj生成し、itemsデータを結合
        const initClickData = {
          event: 'add_to_cart',
          ecommerce: {
            value: clickItem[0].price,
            currency: 'JPY',
            items: clickItem
            }
         };
        
        // データレイヤーへセット
        this.pushDataLayer(initClickData);

        clickItem = [];

        // 内部関数
        function getDefcolorIndex(skuCode, domElement) {
            let result = null;
            domElement.get().forEach((data, index) => {
                if (data.children.length === 0) return;
                let num = index;
                Array.from(data.children).forEach(data => {
                    if(data.classList.contains('sku_' + skuCode) == true) {
                        result = num;
                    } 
                });
            });
            return result;
        };
        function getPrice(skuCode) {
            if ($('[data-gtm-dom-label="defcolorCommodity"] [data-gtm-dom-label="cart-button-wrap"]').length === 0 ) return;
            const index = getDefcolorIndex(skuCode, $('[data-gtm-dom-label="defcolorCommodity"] [data-gtm-dom-label="cart-button-wrap"]'));
            if (typeof index === 'undefined' || index === null) return;
            if ($('.sku_' + skuCode).parents('[data-gtm-dom-label="defcolorCommodity"]').find('[data-gtm-dom-label="price"]').length === 0) return;
            let price = $('.sku_' + skuCode).parents('[data-gtm-dom-label="defcolorCommodity"]').find('[data-gtm-dom-label="price"]')[index].innerText;
            price = parseInt(price.replace(/[^0-9]/g, ''));
            return price;
        };
        function getColorName(skuCode) {
            if ($('[data-gtm-dom-label="defcolorCommodity"] [data-gtm-dom-label="cart-button-wrap"]').length === 0 ) return null;
            const index = getDefcolorIndex(skuCode, $('[data-gtm-dom-label="defcolorCommodity"] [data-gtm-dom-label="cart-button-wrap"]'));
            if (typeof index === 'undefined' || index === null) return;
            if ($('.sku_' + skuCode).parents('[data-gtm-dom-label="defcolorCommodity"]').find('[data-gtm-dom-label="color"]').length === 0) return;
            let colorName = $('.sku_' + skuCode).parents('[data-gtm-dom-label="defcolorCommodity"]').find('[data-gtm-dom-label="color"]')[index].innerText;
            return colorName;
        };
        function setDefcolorCommodityData(skuCode, items) {
            const price = getPrice(skuCode);
            const jsonItems = JSON.stringify(items);
            const defcolorItems = JSON.parse(jsonItems);
            defcolorItems[0].item_id = commodityCode;
            if (typeof colorName === 'undefined') defcolorItems[0].item_colorName = getColorName(skuCode);
            if (typeof price !== 'undefined') defcolorItems[0].price = price;
            return defcolorItems;
        };
    },
    addToWishlist: function (skuCode, sourceDataLayerEventName, sizeLabel, janCode) {
        // dataLayerから指定イベントのobjを探す
        const data = window.dataLayer || null;
        const viewItemData = data.filter((data, index, array) => {
            if(array[index].event == sourceDataLayerEventName) return data;
        });

        // 指定イベントがない場合(クリックイベントとdataLayerが異なる場合)
        if (viewItemData.length === 0) return false;

        // 該当objのitemsデータを取得する
        const clickItem = viewItemData[0].ecommerce.items.filter((data, index, array) => {
            if(array[index].item_id == skuCode.slice(0, -3)) return data;
        });

        // dataLayer内に指定の商品IDが取得できなかった場合
        if (clickItem.length ===0) return false;

        // 属性"data-xxx"から値をセット
        if (typeof skuCode !== 'undefined') clickItem[0].item_variant = skuCode.slice(-3);
        if (typeof skuCode !== 'undefined') clickItem[0].item_sizesku = skuCode;
        if (typeof sizeLabel !== 'undefined') clickItem[0].item_sizeLabel = sizeLabel;
        // if (typeof colorName !== 'undefined') clickItem[0].item_colorName = colorName;
        // if (typeof supplierCode !== 'undefined') clickItem[0].makerID = supplierCode;
        if (typeof janCode !== 'undefined') clickItem[0].janCode = janCode;

        // クリックeventデータのobj生成し、itemsデータを結合
        const initClickData = {
          event: 'add_to_wishlist',
          ecommerce: {
            value: clickItem[0].price,
            currency: 'JPY',
            items: clickItem
            }
         };
        
        // データレイヤーへセット
        this.pushDataLayer(initClickData);
    },
    selectItem: function (commodityCode, sourceDataLayerEventName) {
        // dataLayerから指定イベントのobjを探す
        const data = window.dataLayer || null;
        const viewItemData = data.filter((data, index, array) => {
            if(array[index].event == sourceDataLayerEventName) return data;
        });

        // 指定イベントがない場合(クリックイベントとdataLayerが異なる場合)
        if (viewItemData.length === 0) return false;

        // 該当objのitemsデータを取得する
        const clickItem = viewItemData[0].ecommerce.items.filter((data, index, array) => {
            if(array[index].item_id == commodityCode) return data;
        });

        // dataLayer内に指定の商品IDが取得できなかった場合
        if (clickItem.length === 0) return false;

        var ga4contentCategory = $('#ga4breadcrumbCategories').val();
        var ga4searchString = $('#ga4searchString').val();
        // クリックeventデータのobj生成し、itemsデータを結合
        const initClickData = {
          event: 'select_item',
          ecommerce: {
            value: clickItem[0].price,
            currency: 'JPY',
            items: clickItem
            },
            content_category:ga4contentCategory,
            search_string:ga4searchString
         };
        
        // データレイヤーへセット
        this.pushDataLayer(initClickData);
    },
    pushDataLayer: function (dataLayer) {
        const jsonDataLayer = JSON.stringify(dataLayer);
        const objDataLayer = JSON.parse(jsonDataLayer);
        window.dataLayer = window.dataLayer || [];
        window.dataLayer.push(objDataLayer);
    },
});


// CartJsonから商品情報を取得する際に実行する関数
const viewEventUseCartJson = ({
    commodityData: {},
    dataLayerFn: async function (initData, needsItemCategory) {
        this.commodityData = await setCommodityData();
        if (!this.commodityData) return;
        if(needsItemCategory) {
            viewEvent.dataLayerGenAsyncBreadcrumbsApi(viewEvent.filter(this.commodityData, ITEM_ID), this.commodityData, initData);
        } else {
            viewEvent.pushDataLayer(initData, this.commodityData);
        }
    },
});

// 画面表示時に実行する関数
const viewEvent = ({
    commodityData: setCommodityData(),
    dataLayerFn: function (initData, needsItemCategory) {
        if(needsItemCategory) {
            this.dataLayerGenAsyncBreadcrumbsApi(this.filter(this.commodityData, ITEM_ID), this.commodityData, initData);
        } else {
            this.pushDataLayer(initData, this.commodityData);
        }
    },
    dataLayerGenAsyncBreadcrumbsApi: async function (commodityIdList, commodityData, initData) {
        const breadcrumbsSet = new Set();
        for (const id of commodityIdList) {
            breadcrumbsSet.add(await this.fetchBreadcrumbsApi(id, commodityData, initData));
        };

        const
            breadcrumbsDataMap = this.setBreadcrumbsDataMap(breadcrumbsSet),
            dataLayerItemCategory = this.setDataLayerItemCategory(breadcrumbsDataMap),
            mergedCommodityData = this.setMergeData(dataLayerItemCategory, commodityData);
            this.pushDataLayer(initData, mergedCommodityData);
            if (typeof addShippingInitData !== 'undefined') this.copyDataLayerFn(addShippingInitData, 'purchase', {needsOrderId: false, needsShipping: false});
            if (typeof addPaymentInitData !== 'undefined') this.copyDataLayerFn(addPaymentInitData, 'purchase', {needsOrderId: false, needsShipping: false});
    },
    filter: function (arrayMap, fillterKey) {
        return arrayMap.map((data) => data.get(fillterKey))
    },
    setBreadcrumbsDataMap: function (BreadcrumbsSet) {
        const resultMap = new Map();
        Array.from(BreadcrumbsSet).forEach((fetchData, index) => {
        const fetchDataList = new Array();
        const hasBreadcrumbs = Boolean(fetchData.breadcrumbs.length > 0)
        const ancestors = hasBreadcrumbs ? fetchData.breadcrumbs[0].ancestors : "";
        const active = hasBreadcrumbs ? fetchData.breadcrumbs[0].category_name_pc : "";
        if (ancestors.length > 0) {
            ancestors.forEach(element => {
            fetchDataList.push(element.category_name_pc);
            });
        };
        if (active.length > 0) {
            fetchDataList.push(active);
        };
        resultMap.set(fetchData.commodity_code, fetchDataList);
        });
        return resultMap
    },
    setDataLayerItemCategory: function (fetchDataMap) {
        const resultMap = new Map();
        fetchDataMap.forEach((categories, key) => {
        const fetchDataFnMap = new Map();
        categories.forEach((categoryName, index) => {
            const num = (index === 0) ? "" : index + 1;
            fetchDataFnMap.set("item_category" + num, categoryName);
        });
        resultMap.set(key, fetchDataFnMap);
        });
        return resultMap;
    },
    setMergeData: function (fetchDataLayer, commodityData) {
        const resultArray = new Array();
        fetchDataLayer.forEach((fetchData, key) => {
          commodityData.forEach((commodity) => {
            if (key === commodity.get(ITEM_ID)) {
            resultArray.push(new Map([...commodity, ...fetchData]));
            }
          });
        });
        return resultArray
    },
    fetchBreadcrumbsApi: async function (commodityCode, commodityData, initData) {
        const result = $.ajax({
            type: 'GET',
            dataType: 'jsonp',
            cache : true,
            timeout : 30000,
            url: apiUrlBase + '/commodity-breadcrumbs.jsonp?commodity_code=' + commodityCode + schemaParam,
            jsonpCallback: 'ga4datalayer' + breadcrumbsUniqueNum
        })
        .then((res)=> {
            if (!res.commodity_code.length === 0) {
                const error = new Error('An error occurred while fetching the data.')
                error.status = res.status;
                throw error
            }
            return res;
        })
        .fail((jqXHR, textStatus, errorThrown) => {
            const errorText = textStatus + ', ' + errorThrown;
            let errorPreText ='';
            switch(jqXHR.status) {
                case 400: errorPreText = '400 INVALID_TOKEN. '; break;
                case 401: errorPreText = '401 UNAUTHORIZED. '; break;
                case 500: errorPreText = '500 INTERNAL_SERVER_ERROR. '; break;
                case 502: errorPreText = '502 BAD_GATEWAY. '; break;
                case 404: errorPreText = '404 NOT_FOUND. '; break;
                default: errorPreText = 'UNHANDLED_ERROR. '; break;
            }
            this.pushDataLayer(initData, commodityData);
            throw new Error('No response. ' + errorPreText + errorText );
        });
        return result
    },
    copyDataLayerFn: function (initData, sourceDataLayerEventName, { needsOrderId = null, needsShipping = null } = {}) {
        // dataLayerから指定イベントのobjを探す
        const data = window.dataLayer || null;
        const viewItemData = data.filter((data, index, array) => {
            if(array[index].event == sourceDataLayerEventName) return data;
        }) || null;
        
        // dataLayerから指定イベントを探せなければ中断
        if (viewItemData === null) return;

        // ecommerce情報をマージして、データレイヤー生成へ
        initData.ecommerce = {...viewItemData[0].ecommerce, ...initData.ecommerce};

        // オーダーIDが不要なら削除
        if (needsOrderId === false) delete initData.ecommerce.transaction_id;

        // 配送料が不要なら削除
        if (needsShipping === false) delete initData.ecommerce.shipping;

        this.pushDataLayer(initData);
    },
    pushDataLayer: function (dataLayer, commodityMapData = null) {
        // 商品データがある場合、配列[{map},{map}...]からitemsオブジェクトを生成する
        const items = (commodityMapData == null) ? null : commodityMapData.map((data) => Object.fromEntries(data));

        // itemsがある場合、データレイヤーにセットする
        if( items !== null) {
          dataLayer.ecommerce.items = items;
        }

        // グローバル変数にセットする
        window.dataLayer = window.dataLayer || [];
        window.dataLayer.push(dataLayer);
    }
});

const commonEvent = ({
    getUrlPathName: function () {
      const lang = $('#siteLanguage').val() ?? 'ja';
      const pathName = (lang == 'ja') ? window.location.pathname : window.location.pathname.replace('/' + $('#siteLanguage').val() + '/', '/');
      switch(true) {
          case /^\/brand\/.*$/.test(pathName):
            return 'brand';
          case /^\/cart\/.*$/.test(pathName):
            return 'cart';
          case /^\/category\/.*$/.test(pathName):
            return 'category';
          case /^\/commodity\/.*$/.test(pathName):
            return 'commodity';
          case /(^\/favorite-brand\/.*$|^\/favorite-brand.*$)/.test(pathName):
            return 'favorite-brand';
          case /(^\/search.*$|^\/search\?.*$)/.test(pathName):
            return 'search';
          case /^\/in-shop\/.*$/.test(pathName):
            return 'in-shop';
          default:
            return 'other';
      }
    },
    getUrlPageName: function (id) {
      switch(id) {
          case 'brand':
            return 'ブランド商品一覧ページ';
          case 'cart':
            return 'カート';
          case 'category':
            return 'カタログページ';
          case 'commodity':
            return '商品詳細ページ';
          case 'favorite-brand':
            return 'マイブランド商品一覧ページ';
          case 'search':
            return '検索結果ページ';
          case 'in-shop':
            return 'ショップ商品一覧ページ';
          default:
            return 'その他ページ';
      }
    }
});