(function (doc) {
    'use strict';
    const LANG = 'ja';
    const PAGER_PREV_TEXT = '前へ';
    const PAGER_NEXT_TEXT = '次へ';
    const SEARCH_RESULT_HEAD_TEXT = '検索結果';
    const SEARCH_RESULT_TEXT = (firstResult, lastResult, totalResults, query) => `「${query}」の検索結果${totalResults}件<br><span class="font-weight-bold">${firstResult}</span> ～ <span class="font-weight-bold">${lastResult}</span>件目を表示`;

    const matchMedia = window.matchMedia('(max-width: 767px)');
    const tocElement = document.querySelector('.m-toc');
    let searchEngine;

    
    class SearchEngine {
        constructor(data) {
            this.data = data;
            this.pageCount = 1;
            this.pageSize = 10;
            this.query = '';

            const segmenter = Intl.Segmenter && new Intl.Segmenter(LANG, { granularity: "word" });
            this.miniSearch = new MiniSearch({
                fields: ['contents'],                       
                storeFields: ['title', 'contents', 'file'], 
                processTerm: (term) => {
                    if (!segmenter) return term.toLowerCase();  

                    
                    
                    
                    const tokens = [];
                    for (const seg of segmenter.segment(term)) {
                        tokens.push(seg.segment.toLowerCase());
                    }
                    return tokens;
                },
            });
            this.miniSearch.addAll(data);
        }
        
        
        search(query) {
            this.query = query;
            this.results = this.miniSearch.search(query, {prefix: true});

            
            let equalQueryRresults = [];
            if (query !== '') {
                for (const pageItem of this.data) {
                    if (pageItem.contents.toLowerCase().indexOf(this.query.toLowerCase()) > - 1) {
                        equalQueryRresults.push(pageItem);
                        equalQueryRresults[equalQueryRresults.length - 1]['queryTerms'] = [ this.query ];
                    }
                }
            }
            this.results.push(...equalQueryRresults);
            this.results = this.results.filter( (result, index, self) => self.map(val => val.id).indexOf(result.id)===index);

            
            this.results = this.results.filter(result => {
                let queryTerms = result.queryTerms.filter(queryTerm => {
                    if (this.query.length !== 1 && queryTerm.length === 1) {
                        let unicode = queryTerm.charCodeAt(0);
                        return !((unicode >= 0x3040 && unicode <= 0x309F) || (unicode >= 0x30A0 && unicode <= 0x30FF));
                    }
                    return true;
                })
                return queryTerms.length !== 0;
            });
            for (let i = this.results.length -1; i > -1; i--) {
                const result = this.results[i];
                let queryTerms = result.queryTerms.filter(queryTerm => {
                    if (this.query.length !== 1 && queryTerm.length === 1) {
                        let unicode = queryTerm.charCodeAt(0);
                        return !((unicode >= 0x3040 && unicode <= 0x309F) || (unicode >= 0x30A0 && unicode <= 0x30FF));
                    }
                    return true;
                })
                if (queryTerms.length === 0) {
                    queryTerms.splice(i, 1);
                }
                else {
                    this.results[i].queryTerms = queryTerms;
                }
            }

            
            this.results.sort((a, b) => {
                if ((a.contents.toLowerCase().indexOf(this.query.toLowerCase()) === -1) && (b.contents.toLowerCase().indexOf(this.query.toLowerCase()) > -1)) return 1;
                else if ((a.contents.toLowerCase().indexOf(this.query.toLowerCase()) > -1) && (b.contents.toLowerCase().indexOf(this.query.toLowerCase()) === -1)) return -1;
                return 0;
            });

            this.pageCount = Math.ceil(this.results.length / this.pageSize);
        }
    
        
        displayPage(pageNumber) {
            let start = (pageNumber - 1) * this.pageSize;
            let end = start + this.pageSize;
            let pageItems = this.results.slice(start, end);
            let usedQueryTerms = [...new Set([this.query, ...this.query.split(' ')])];  
            
            
            let htmlContent = `<div class="m-heading-2">
<h2 class="m-heading-2__title page-header">${SEARCH_RESULT_HEAD_TEXT}</h2>
<!--/.m-heading-2--></div>
<div class="m-box-field">
<div class="m-container">
<div class="m-paragraph">
<div class="m-paragraph__body">
<p>${SEARCH_RESULT_TEXT(Math.min(this.results.length, 10 * (pageNumber - 1) + 1), Math.min(this.results.length, 10 * pageNumber), this.results.length, escapeHTML(this.query))}</p></div>
<!--/.m-paragraph--></div>
<!--/.m-container--></div>
<!--/.m-box-field--></div>
<div class="m-box-result">`;
            pageItems.forEach(pageItem => {
                let searchContent = pageItem.contents;
                let resultContent = '';
                let queryTerms = [...new Set([this.query, ...pageItem.queryTerms])];
                let maxContentLength = 100;

                for (let queryTerm of queryTerms) {
                    let index = searchContent.toLowerCase().indexOf(queryTerm.toLowerCase());
                    if (index === -1) {
                        if (queryTerms.indexOf(queryTerm) === queryTerms.length - 1) {
                            
                            resultContent = searchContent.substring(0, maxContentLength) +  ( searchContent.length <= maxContentLength ? '' : '...' );
                            break;
                        }
                    }
                    else if (index < maxContentLength - queryTerm.length) {
                        
                        resultContent = searchContent.substring(0, maxContentLength) +  ( searchContent.length <= maxContentLength ? '' : '...' );
                        usedQueryTerms = [...new Set([...usedQueryTerms, ...queryTerms])];
                        break;
                    }
                    else if (index + queryTerm.length + maxContentLength / 2 >= searchContent.length) {
                        
                        resultContent = searchContent.substring(searchContent.length - maxContentLength);
                        usedQueryTerms = [...new Set([...usedQueryTerms, ...queryTerms])];
                        break;
                    }
                    else if (index > -1) {
                        
                        let startIndex = Math.max(0, index - maxContentLength / 4);
                        let lastIndex = startIndex + maxContentLength;
                        resultContent = searchContent.substring(startIndex, lastIndex) + '...';
                        usedQueryTerms = [...new Set([...usedQueryTerms, ...queryTerms])];
                        break;
                    }
                }

                
                htmlContent += '<div>';
                htmlContent += '<div class="m-heading-3 mb-0">';
                htmlContent += '<h3 class="m-heading-3__title page-header typesquare_option">';
                htmlContent += `<a href="${pageItem.file}" target="_blank" rel="noopener" class="btn btn-link">${escapeHTML(pageItem.title).replaceAll('\n', '').replaceAll('\ufffc', ' ')}</a></h3>`;
                htmlContent += '</div>';
                htmlContent += '<div class="m-paragraph">';
                htmlContent += '<div class="m-paragraph__body">';
                htmlContent += `<p>${escapeHTML(resultContent).replaceAll('\n', ' ').replaceAll('\ufffc', ' ').replaceAll('\r', '<br>')}</p>`;
                htmlContent += '</div>';
                htmlContent += '<!-- /.m-paragraph --></div>';
                htmlContent += '</div>';
            });

            htmlContent += `</div>`

            
            if (this.results.length > 0) {
                
                let maxIndex = Math.ceil(this.results.length / 10);
                let startIndex = Math.max(1, (pageNumber - 3) - (Math.max(maxIndex, (pageNumber + 3)) - maxIndex));
                let endIndex = Math.min(maxIndex, (pageNumber + 3) + (Math.max(1, (pageNumber - 3)) - (pageNumber - 3)));
                htmlContent += `<div class="m-pager"><ul class="pager-01"><li class="prev">`;
                if (pageNumber == 1) {
                    htmlContent += `<span class="SS_prevPage_disable">${PAGER_PREV_TEXT}</span>`;
                }
                else {
                    htmlContent += `<span class="SS_prevPage"><a class="btn-link-inline" href="#">${PAGER_PREV_TEXT}</a></span>`;
                }
                htmlContent += `</li><li class="counter"><ul>`;
                for (let i = startIndex; i < endIndex + 1; i++) {
                    if (i == pageNumber) {
                        htmlContent += `<li class="-active">${i}</li>`;
                    }
                    else if (i === endIndex && endIndex < maxIndex) {   
                        htmlContent += `<li class="m-pager-overflow">⋯</li>`;
                    }
                    else {
                        htmlContent += `<li><a href="#">${i}</a></li>`;
                    }
                }
                htmlContent += `</ul></li><li class="next">`;
                if (pageNumber == maxIndex) {
                    htmlContent += `<span class="SS_nextPage_disable">${PAGER_NEXT_TEXT}</span>`;
                }
                else {
                    htmlContent += `<span class="SS_nextPage"><a class="btn-link-inline" href="#">${PAGER_NEXT_TEXT}</a></span>`;
                }
                htmlContent += `</li></ul></div>`;
            }

            
            doc.querySelector('.m-box-searchResult').innerHTML = htmlContent;

            
            let instance = new Mark(doc.querySelectorAll('.m-box-result'));
            for (let queryTerm of usedQueryTerms) {
                instance.mark(queryTerm, { 'separateWordSearch': false, 'accuracy': 'partially', 'caseSensitive': false, 'diacritics': false });
            }

            
            doc.querySelector('.m-pager .SS_prevPage a')?.addEventListener('click', function(event) {
                event.preventDefault();
                searchEngine.displayPage(pageNumber - 1);
                doc.querySelector('.m-page-top__btn').click();
            });
            document.querySelector('.m-pager .SS_nextPage a')?.addEventListener('click', function(event) {
                event.preventDefault();
                searchEngine.displayPage(pageNumber + 1);
                doc.querySelector('.m-page-top__btn').click();
            });
            doc.querySelectorAll('.m-pager .counter > ul > li')?.forEach((element) => {
                element.querySelector('a')?.addEventListener('click', function(event) {
                    event.preventDefault();
                    searchEngine.displayPage(parseInt(event.target.textContent, 10));
                    doc.querySelector('.m-page-top__btn').click();
                });
            });
        }
        
        escapeHtml(str) {
            return str
                 .replace(/&/g, "&amp;")
                 .replace(/</g, "&lt;")
                 .replace(/>/g, "&gt;")
                 .replace(/"/g, "&quot;")
                 .replace(/'/g, "&#039;");
         }
    }
    
    
    window.addEventListener('resize', function() {
        mobileLayout();
        pcLayout();
    });
    
    
    window.addEventListener('message', function (e) {
        doc.querySelector(`[data-id="${e.data}"]`)?.click();
    });

    
    (function() {
        mobileLayout();
        pcLayout();
        
        
        let searchParams = new URLSearchParams(window.location.search);
        if (searchParams.has('query')) {
            let findWord = searchParams.get('query');
            document.querySelector('.m-form__input').value = findWord;
            document.querySelector('.m-form__input').classList.add('-inputed');
            searchResult(findWord);
        }
    }());

    
    
    
    function mobileLayout() {
        if (matchMedia.matches) {
            if (document.querySelector('.js-global-menu-root .m-toc') === null) {
                document.querySelector('.js-global-menu-root > .m-global-menu__wrap > .m-global-menu__wrap__inner').appendChild(tocElement);
            }
        }
    }

    
    
    
    function pcLayout() {
        if (!matchMedia.matches) {
            if (tocElement !== null) {
                if (document.querySelector('main .l-container .l-side *') === null) {
                    document.querySelector('main .l-container .l-side').appendChild(tocElement);
                }
            }
        }
    }

    
    
    
    
    function searchResult(findWord, findStartIndex = 1, findEndIndex = 10) {
        searchEngine = new SearchEngine(SearchContents);
        
        searchEngine.search(findWord);
        searchEngine.displayPage(1);
    }

    doc.querySelectorAll('.m-slider__ui').forEach((e) => {
        e.style.setProperty('display', 'block', 'important');

    });
    
    function escapeHTML(str) {
        return str.replace(/[&<>"']/g, function(match) {
            const escapeMap = {
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '"': '&quot;',
                "'": '&#39;'
            };
            return escapeMap[match];
        });
    }

}(window.document));
