var qahm = qahm || {};

qahm.brainTalkNo = 0;
qahm.brainProcessNo = 0;

createdBrain = {};
const loadingElement = '<span class="el_loading">Loading<span></span></span>';
document.addEventListener("DOMContentLoaded", function() {
    qahm.createBrain();
});

// キャラクターのクリックイベントを無効化するフラグ
qahm.isCharaClickDisabled = false;

qahm.createBrain = function(brainSlug = 'official_brain', connectStep = 'start') {
    switch (connectStep) {
        case 'start':
            qahm.createBrain(brainSlug, 'getAllBrains');
            break;

        case 'getAllBrains':
            jQuery.ajax({
                type: 'POST',
                url: qahm.ajax_url,
                dataType: 'json',
                data: {
                    'action': 'qahm_ajax_get_brains',
                    'nonce': qahm.nonce_api,
                }
            })
            .done(function(data) {
                if (data.success) {
                    qahm.allBrains = data.data;
                    qahm.createBrain(brainSlug, 'createBrainsSelector');
                }
            })
            .fail(function(jqXHR, textStatus, errorThrown) {
                console.log('Error: ' + errorThrown);
            })
            .always(function() {
                // This function will always be called
            });
            break;

        case 'createBrainsSelector':
            if (qahm.checkBrainsPage()) {
                qahm.createBrainsSelector();
            } else {
                qahm.createBrain(brainSlug, 'createBrainsContainer');
            }
            break;

        case 'createBrainsContainer':
            qahm.createBrainsContainer(brainSlug);
            qahm.createBrain(brainSlug, 'ajaxConnectBrain');
            break;

        case 'ajaxConnectBrain':
            qahm.ajaxConnectBrain(brainSlug, qahm.brainTalkNo, 'start');
            qahm.brainTalkNo++;
            break;
    }
}

qahm.checkBrainsPage = function( ) {
    const element = document.getElementById('this_page_is_brainpage');
    if (element) {
        return true;
    } else {
        return false;
    }
}

qahm.createBrainsSelector = function() {
    // HTMLを生成
    let html = `
	<div class="qa-zero-brains-selector-inner">
	<div class="qa-zero-brains-selector-title">${qahml10n['select_agent']}</div>
		<div class="qa-zero-brains-selector-cards">
		`;

    Object.keys(qahm.allBrains).forEach((key) => {
		const brain = qahm.allBrains[key];
		html += `
		<div class="qa-zero-brains-selector-card" data-brain-slug="${brain.slug}">
			<img class="qa-zero-brains-selector-image" src="${brain.images.default}" alt="${brain.description}">
			<div class="qa-zero-brains-selector-name" data-brain-slug="${brain.slug}">${brain.name}</div>
			<div class="qa-zero-brains-selector-description">${brain.description}</div>
			<div class="qa-zero-brains-selector-version">version ${brain.version}</div>
		</div>
		`;
    });

    html += '</div></div>';

    document.getElementById('qa-zero-brains-selector').innerHTML = html;
	
	// ▼ Sortable.js を使用して並び替え機能を追加
	const container = document.querySelector('.qa-zero-brains-selector-cards');
	const storageKey = 'brains-selector-sort-order';

	// ▼ 並び順を復元する
	function restoreOrder() {
		const savedOrder = JSON.parse(localStorage.getItem(storageKey) || '[]');
		const currentEls = Array.from(container.children);
		const currentIds = currentEls.map(el => el.getAttribute('data-brain-slug'));

		const fragment = document.createDocumentFragment();

		// 保存されていたIDのうち、今存在するものを並べる
		savedOrder.forEach(slug => {
			if (currentIds.includes(slug)) {
			const el = container.querySelector(`[data-brain-slug="${slug}"]`);
			if (el) fragment.appendChild(el);
			}
		});

		// 新しく追加された要素（保存データにないID）を末尾に追加
		currentEls.forEach(el => {
			const id = el.getAttribute('data-brain-slug');
			if (!savedOrder.includes(id)) {
			fragment.appendChild(el);
			}
		});

		container.appendChild(fragment);
	}

	// ▼ 並び順を保存する
	function saveOrder() {
		const order = [...container.children].map(el => el.getAttribute('data-brain-slug'));
		localStorage.setItem(storageKey, JSON.stringify(order));
	}
	
	// ▼ Sortable を初期化
	new Sortable(container, {
		animation: 200,
		ghostClass: 'qa-zero-brains-selector-drag-ghost',
		chosenClass: 'qa-zero-brains-selector-drag-chosen',
		onEnd: saveOrder
	});

	// ▼ 最初に並び順を復元
	restoreOrder();

	// ▲ Sortable.js を使用して並び替え機能を追加

    // セルがクリックされたときの処理をセット
    let cards = document.querySelectorAll('.qa-zero-brains-selector-card');
    cards.forEach(card => {
        card.addEventListener('click', function handler(event) {
            if (qahm.isCharaClickDisabled) {
                return;
            }

            qahm.isCharaClickDisabled = true;

            if (event.currentTarget.contains(event.target)) {
                let header = document.querySelector('.qa-zero-header__title');
                if ( header ) {
                    header.style.cursor = 'pointer';
                    header.addEventListener('click', function() {
                        location.reload();
                        exit;
                    });
                }

                let newBrainSlug = card.dataset.brainSlug;
                if (newBrainSlug) {
                    qahm.createBrain(newBrainSlug, 'createBrainsContainer');
                }
                document.getElementById('qa-zero-brains-selector').classList.add('qa-zero-hide');
            }
        }, {once: false});

        card.addEventListener('mouseover', function() {
            card.classList.add('focused');
        });

        card.addEventListener('mouseout', function() {
            card.classList.remove('focused');
        });
    });
}

qahm.ajaxConnectBrain = function(brainSlug, brainTalkNo, state = 'start', free = null, retryCount = 0) {
    let url = new URL(window.location.href);
    let params = url.searchParams;
    let tracking_id = params.get('tracking_id');

    let aiflag = false;
    if (state.substring(0, 2) === 'ai') {
        aiflag = true;
        const commandBox = document.querySelector('.qa-zero-brain-command-box');
        if (commandBox) {
            commandBox.innerHTML = loadingElement;
        }
    }
    jQuery.ajax(
        {
            type: 'POST',
            url: qahm.ajax_url,
            dataType : 'json',
            data: {
                'action' : 'qahm_ajax_connect_brain',
                'brain_slug' : brainSlug,
                'state' : state,
                'free' : free,
                'nonce': qahm.nonce_api,
                'tracking_id': tracking_id
            }
        }
    ).done(
        function( data ){
            if (data.success) {
                qahm.executeBrain(brainSlug, brainTalkNo, data.data);
            }
            if (aiflag) {
                const commandBox = document.querySelector('.qa-zero-brain-command-box');
                if (commandBox) {
                    commandBox.innerHTML = '';
                }
            }
        }
    ).fail(
        function( jqXHR, textStatus, errorThrown ){
            console.log('Error: ' + errorThrown);
            if (aiflag) {
                const commandBox = document.querySelector('.qa-zero-brain-command-box');
                if (commandBox) {
                    commandBox.innerHTML = 'Something went wrong. Retrying...';
                }
            }
            if (retryCount < 3) {
                qahm.ajaxConnectBrain(brainSlug, brainTalkNo, state, null, retryCount + 1);
            } else {
                qahm.connectBrainFailed();
                console.log('Failed to connect to brain after 3 attempts.');
            }
        }
    ).always(
        function(){
            qahm.isCharaClickDisabled = false;
        }
    );
}

qahm.createBrainsContainer = function( brainSlug = 'official_robot' ) {

    // IDを指定して既存のnewDev要素を取得
    let element = document.getElementById(qahm.nowBrainContainerId);
    if (element) {
        element.parentNode.removeChild(element);
    }

    qahm.brainTalkNo = 0;
    qahm.brainProcessNo = 0;
    qahm.brainTable = undefined;

    let newDiv = document.createElement("div");
    let mainCharacterImage = '';
    let mainCharacterName = '';
    let mainCharacterVersion = '';
    let mainCharacterTooltip = '';
    let brainsSelectBoxHtml = '<select id="qa-zero-brain-change"><option selected>-- ' + qahml10n['switch_agent'] + ' --</option>';
    for (let brain in qahm.allBrains) {
        if (qahm.allBrains.hasOwnProperty(brain)) {
            if ( brainSlug === brain ) {
                mainCharacterImage = qahm.allBrains[brain].images.default;
                mainCharacterName = qahm.allBrains[brain].name;
                mainCharacterVersion = qahm.allBrains[brain].version;
                if (typeof qahm.allBrains[brain].description !== 'undefined') {
                    mainCharacterTooltip = 'class="brain-tooltip" tabindex="0" title="' + qahm.allBrains[brain].description + '"';
                }
            }
        }
        brainsSelectBoxHtml += '<option value="' + qahm.allBrains[brain].slug + '">' + qahm.allBrains[brain].name + '</option>';
    }
    brainsSelectBoxHtml += '<option value="reload"> ' + qahml10n['return_to_brains_home'] + ' </option>';
    brainsSelectBoxHtml += '</select>';
    qahm.nowBrainContainerId = `${brainSlug}-container`;
    newDiv.innerHTML = `
<div id="${brainSlug}-container">
<div class="qa-zero-brain-container">
<div class="qa-zero-brain-change-box">
${brainsSelectBoxHtml}
</div>
<div class="qa-zero-character-box">
<div class="qa-zero-main-character-box">
<div class="qa-zero-main-character-image"><img src="${mainCharacterImage}" alt="${mainCharacterName}" ${mainCharacterTooltip}></div>
</div>
</div>
<div class="qa-zero-brain-talk-box">
<div class="qa-zero-brain-talk-box-header">
    <div class="qa-zero-brain-talk-box-title">
${mainCharacterName}
    </div>
</div>
<div id="qa-zero-brain-talk-${qahm.brainTalkNo}" class="qa-zero-brain-dialogue-box">
</div>
</div>
</div>
</div>
`;

    // 直接新Divを対象要素に追加
    let container = document.getElementById('this_page_is_brainpage');
    if (container) {
        container.appendChild(newDiv);
    }
    
    const selectBox = document.getElementById('qa-zero-brain-change');
    selectBox.addEventListener('change', function(event) {
        if (qahm.isCharaClickDisabled) {
            return;
        }
        qahm.isCharaClickDisabled = true;
        let newBrainSlug = event.target.value;
        if ( newBrainSlug === 'reload' ) {
            location.reload();
            exit;
        }
        if (newBrainSlug) {
            qahm.createBrain(newBrainSlug, 'createBrainsContainer');
        }
    }, {once: false});
}

qahm.executeBrain = function( brainSlug = 'official_robot', brainTalkNo, executeJson ) {
    processExecute(brainSlug, brainTalkNo, executeJson.execute);
}

const processExecute = async (brainSlug = 'official_robot', brainTalkNo, executeObj) => {
    const talkElem = document.getElementById('qa-zero-brain-talk-' + brainTalkNo);
    for (let key in executeObj) {
        if (talkElem === null || typeof talkElem === 'undefined') {
            return;
        }
        const processNo = qahm.brainProcessNo;
        qahm.brainProcessNo++;
        let itemKey = Object.keys(executeObj[key])[0];
        let value = executeObj[key][itemKey];
        switch (itemKey) {
            case 'msg':
                // メッセージの表示が完了するまで待機
                await displayTextLikeGame(value, talkElem, false);
                break;
            case 'cmd':
                await new Promise((resolve) => {
                    let commandBox = document.createElement('div');
                    commandBox.classList.add('qa-zero-brain-command-box');
                    for (let cmdKey in value) {
                        if (value.hasOwnProperty(cmdKey)) {
                            let button = document.createElement('button');
                            button.classList.add('qa-zero-brain-command-box__button');
                            button.textContent = value[cmdKey].text;
                            if ( button.textContent === qahml10n['end_command_label'] ) {
                                button.classList.add('qa-zero-brain-command-box__button-end');
                            }
                            if (value[cmdKey].action) {
                                if (value[cmdKey].action.link) {
                                    button.addEventListener('click', () => {
                                        window.location.href = value[cmdKey].action.link;
                                    });
                                }
                                if (value[cmdKey].action.close) {
                                    button.addEventListener('click', () => {
                                        if (value[cmdKey].action.close === 'window') {
                                            newWindow.close();
                                        }
                                    });
                                }
                                if (value[cmdKey].action.next) {
                                    button.addEventListener('click', () => {
                                        if (value[cmdKey].action.next === 'start') {
                                            brainMessageAllClear(talkElem);
                                        } else {
                                            displayTextLikeGame(button.innerText, talkElem, true);
                                        }
                                        let free = null;
                                        if ( value[cmdKey].action.free ) {
                                            free = value[cmdKey].action.free;
                                        }
                                        qahm.ajaxConnectBrain(brainSlug, brainTalkNo, value[cmdKey].action.next, free);
                                        button.remove();
                                        if (commandBox && commandBox.parentNode) {
                                            commandBox.remove();
                                        }
                                        resolve();
                                    });
                                }
                            }
                            commandBox.appendChild(button);
                        }
                    }
                    talkElem.appendChild(commandBox);
                    talkElem.scrollTop = talkElem.scrollHeight;
                });
                break;
            case 'data':
                await new Promise((resolve) => {
                    if (typeof qahm.brainTable === 'undefined') {
                        qahm.brainTable = [];
                    }

					// formatterプロパティがある場合は文字列を関数に変換
					for (let i = 0; i < value.header.length; i++) {
						if (value.header[i].formatter !== undefined) {
							value.header[i].formatter = eval(`(${value.header[i].formatter})`);
						}
					}

                    let tableKey = "tb_brain-" + processNo;
                    let fragment = document.createDocumentFragment();
                    let containerDiv = document.createElement("div");
                    containerDiv.className = 'qa-zero-data-container';
                    let zeroDataDiv = document.createElement("div");
                    zeroDataDiv.className = 'qa-zero-data';
                    containerDiv.appendChild(zeroDataDiv);
                    let newTitle = document.createElement("div");
                    newTitle.textContent = value.title;
                    newTitle.id = tableKey + '-title';
                    newTitle.className = 'qa-zero-data__title';
                    zeroDataDiv.appendChild(newTitle);
                    let newDiv = document.createElement("div");
                    newDiv.id = tableKey;
                    zeroDataDiv.appendChild(newDiv);
                    fragment.appendChild(containerDiv);
                    talkElem.appendChild(fragment);

					qahm.brainTable[tableKey] = qaTable.createTable('#' + tableKey, value.header, value.option);
					qahm.brainTable[tableKey].updateData( value.body );

                    resolve();
                });
                break;
        }
        await new Promise(resolve => setTimeout(resolve, 500));
    }
}

qahm.connectBrainFailed = function( ) {
    const commandBox = document.querySelector('.qa-zero-brain-command-box');
    commandBox.innerHTML = 'Sorry, we tried 3 times but failed. Please select a Brain again and try running it once more.';
}

qahm.getSelectorPath = function (element) {
    let path = [];
    while (element && element.parentNode) {
        let selector = element.nodeName.toLowerCase();
        if (element.id) {
            selector += '#' + element.id;
        } else if (element.className && typeof element.className === 'string') {
            selector += '.' + element.className.split(' ').join('.');
        }
        path.unshift(selector);
        element = element.parentNode;
    }
    return path.join(' > ');
}

function displayTextLikeGame(html, dialogueBox, isCommand) {
    return new Promise((resolve, reject) => {
        const targetElement = dialogueBox;
        if (!targetElement) {
            console.error(`Element dialogueBox not found.`);
            reject(new Error("Element dialogueBox not found"));
            return;
        }
        const parser = new DOMParser();
        const doc = parser.parseFromString(html, 'text/html');
        const nodes = Array.from(doc.body.childNodes);
        let charIndex = 0;
        let nodeIndex = 0;
        let currentParagraph = null;
        const intervalId = setInterval(() => {
            if (nodeIndex >= nodes.length) {
                clearInterval(intervalId);
                setupPxLinkEvents(targetElement);
                resolve();
                return;
            }
            const node = nodes[nodeIndex];
            if (node.nodeType === Node.TEXT_NODE) {
                if (!currentParagraph) {
                    currentParagraph = document.createElement('div');
                    currentParagraph.classList.add('qa-zero-brain-dialogue-box-message');
                    targetElement.appendChild(currentParagraph);
                    if (isCommand) {
                        currentParagraph.classList.add('qa-zero-brain-dialogue-box-command');
                    }
                }
                let contentToAdd = node.textContent[charIndex];
                currentParagraph.innerHTML += contentToAdd;
                charIndex++;
                if (charIndex >= node.textContent.length) {
                    charIndex = 0;
                    nodeIndex++;
                }
            } else {
                if (!currentParagraph) {
                    currentParagraph = document.createElement('div');
                    currentParagraph.classList.add('qa-zero-brain-dialogue-box-message');
                    targetElement.appendChild(currentParagraph);
                    if (isCommand) {
                        currentParagraph.classList.add('qa-zero-brain-dialogue-box-command');
                    }
                }
                currentParagraph.appendChild(node.cloneNode(true));
                nodeIndex++;
            }
            targetElement.scrollTop = targetElement.scrollHeight;
        }, 15);
    });
}

function convertPxToLink(text) {
    return text.replace(/(\d+)px/g, (match, p1) => {
        return `<span class="pxlink" data-scroll="${p1}" style="text-decoration: underline">${match}</span>`;
    });
}

function setupPxLinkEvents(targetElement) {
    const pxLinks = targetElement.querySelectorAll('.pxlink');
    pxLinks.forEach(link => {
        link.addEventListener('click', (event) => {
            let iframe = document.getElementById('heatmap-iframe');
            let iframeWindow = iframe.contentWindow;
            const position = event.target.getAttribute('data-scroll');
            let windowHeight = iframeWindow.innerHeight;
            let scrollToPosition = position - (windowHeight / 2);
            iframeWindow.scrollTo({
                top: scrollToPosition,
                behavior: 'smooth'
            });
        });
    });
}

function brainMessageAllClear(dialogueBox) {
    dialogueBox.innerHTML = '';
    qahm.brainTalkNo = 0;
    qahm.brainProcessNo = 0;
    qahm.brainTable = undefined;
}
