const Vue = require("vue");

class BasePageListLoader {
    loadPageList() {
        return Promise.reject(new Error('Not implemented'));
    }

    parseHTMLString(txt) {
        try {
            let parser = new DOMParser();
            let xmlDoc = parser.parseFromString(txt, "text/html");
            return xmlDoc;
        } catch(e) {
            console.error(e.message);
        }
        return null;
    }

    loadPageContent(pageInfo) {
        return new Promise((resolve, reject) => {
            if (!pageInfo || !pageInfo.fullTitle) {
                return reject(new Error('pageInfo.fullTitle is null'));
            }

            let url = mw.util.getUrl(pageInfo.fullTitle);
            if (url.indexOf('?') >= 0) {
                url += '&';
            } else {
                url += '?'
            }
            url += 'action=render';
            
            fetch(url, {
                method: 'GET',
                headers: {
                    'Content-Type': 'text/html; charset=UTF-8'
                }
            }).then((response) => {
                if (!response.ok) {
                    if (response.status === 404) {
                        throw new Error(mw.message('isekai-preview-page-list-load-error-404').parse());
                    } else if (response.status === 403) {
                        throw new new Error(mw.message('isekai-preview-page-list-load-error-403').parse());
                    } else {
                        throw new new Error(mw.message('isekai-preview-page-list-load-error-http-status', response.statusText).parse());
                    }
                }
                return response.text();
            }).then((str) => {
                let $dom = $(this.parseHTMLString(str));
                let $content = $dom.find('.mw-parser-output');
                if ($content.length > 0) {
                    //删除目录
                    $content.find('.toc').remove();
                    resolve($content.html());
                } else {
                    throw new Error('Cannot find content');
                }
            }).catch((error) => {
                if (error instanceof TypeError) {
                    error = new Error(mw.message('isekai-preview-page-list-load-error-parse').parse());
                }
                reject(error);
            });
        });
    }

    getPageUrl(pageInfo) {
        return new Promise((resolve, reject) => {
            if (!pageInfo || !pageInfo.fullTitle) {
                return reject(new Error('pageInfo.fullTitle is null'));
            }

            let url = mw.util.getUrl(pageInfo.fullTitle);
            resolve(url);
        });
    }

    /**
     * 根据标题生成页面信息
     * @param {string} title 
     * @returns 
     */
    makePageInfoFromTitle(title) {
        let pageInfo = {
            fullTitle: title,
            title: title,
            subTitle: null
        };
        if (title.indexOf('/') !== 0) {
            let splitPos = title.lastIndexOf('/');
            pageInfo.title = title.substring(splitPos + 1);
            pageInfo.subTitle = title.substring(0, splitPos);
        }
        return pageInfo;
    }
}

class PresetPageListLoader extends BasePageListLoader {
    /**
     * 从页面列表加载页面
     * @param {string[]} pageList 
     */
    constructor(pageList) {
        super();

        this.pageList = pageList.map((pageTitle) => {
            return this.makePageInfoFromTitle(pageTitle);
        });
    }

    /**
     * 加载页面列表
     * @returns {Promise<*>}
     */
    loadPageList() {
        return Promise.resolve(this.pageList);
    }
}

class CategoryPageListLoader extends BasePageListLoader {
    /**
     * 从分类加载页面
     * @param {string} category 
     */
    constructor(category) {
        super();

        this.category = category;
        this.api = new mw.Api();
    }

    /**
     * 加载页面列表
     * @returns {Promise<*>}
     */
    loadPageList() {
        return new Promise((resolve, reject) => {
            this.api.get({
                action: 'query',
                list: 'categorymembers',
                cmtitle: this.category,
                cmtype: 'page',
                cmnamespace: 0,
                cmlimit: 200,
                cmsort: 'sortkey',
            }).done((data) => {
                if(data.query && data.query.categorymembers){
                    let pageList = data.query.categorymembers.map((pageInfo) => {
                        return this.makePageInfoFromTitle(pageInfo.title);
                    });
                    resolve(pageList);
                } else if(data.error){
                    reject(new Error(data.error.info));
                } else {
                    reject(new Error(mw.message('isekai-discover-error-cannotload').parse()));
                }
            }).fail((data) => {
                reject(new Error(data.error.info));
            });
        });
    }
}

function htmlDecode(input) {
  var doc = new DOMParser().parseFromString(input, "text/html");
  return doc.documentElement.textContent;
}

(function() {
    // 打印模式下不加载
    var mediaQueryList = window.matchMedia('print');
    if (mediaQueryList.matches) {
        return;
    }

    let previewPageList = document.querySelectorAll('.isekai-preview-page-list-card');
    if (previewPageList.length > 0) {
        const App = require("./PreviewPageList.vue");
        previewPageList.forEach((previewPageListDom) => {
            try {
                let props = {};
                let dataset = previewPageListDom.dataset;

                props.autoFocus = (dataset.autofocus == '1');
                props.lazyLoad = (dataset.lazyload == '1');

                switch (dataset.loader) {
                    case 'pages':
                        let pagesJsonEl = document.querySelector('script[type="application/json"][data-pages]');
                        let pageList = [];
                        if (pagesJsonEl) {
                            let jsonStr = htmlDecode(pagesJsonEl.innerText);
                            pageList = JSON.parse(jsonStr);
                        }
                        props.pageListLoader = new PresetPageListLoader(pageList);
                        break;
                    case 'category':
                        let category = dataset.category;
                        props.pageListLoader = new CategoryPageListLoader(category);
                        break;
                    default:
                        console.error('Unknown loader: ' + dataset.loader);
                }

                Vue.createMwApp(App, props).mount(previewPageListDom);
            } catch (e) {
                console.error(e);
            }
        });
    }
})();