const {parse} = require('node-html-parser');
const {decodeHTML} = require('../lib')
module.exports = class ReaperModule 
{

    /**
     * @property {Scanlator} scanlator - Scanlator name
     * @typedef {String} Scanlator
     * @pattern /^[\w-]+-scans$/
     */
    constructor()
    {
        this.scanlator = 'Reaper-scans';
        this.BaseLink = 'https://reaper-scans.com/';
        this.timeout = 5000;
    }
    /**
     * 
     * @param {String} query 
     * @returns {Array<Manga>}
     * @typedef {Object} Manga
     * @property {Link} link - Manga Link
     * @property {String} title - Manga Title
     * @property {String} Status - Manga Status
     * @property {Link} img - Image Link
     * @property {Number} latestChap - Latest Chapter Number
     * @typedef {String} Link
     */
    async Search(query)
    {
        return await fetch(this.BaseLink+'?s='+query, {timeout:this.timeout})
            .then(handleResponse)
            .then(handleData)
            .catch(handleError);
            function handleResponse(response) 
            {
                return response.text();
            }
            function handleError(error) 
            {
                return error;
            }
            function handleData(data) 
            {
                data = data.split('<div class="listupd">')[1].split('<div class="pagination">')[0]
                const document = parse(data);
                let payload = [];
                for(var result of document.querySelectorAll('a'))
                {
                    let aux = {
                        link:result.rawAttrs.split('"')[1],
                        title:result.rawAttrs.split('"')[3],
                        img:result.querySelectorAll('.limit > img')[0].rawAttrs.split('"')[1],
                        status:result.querySelector('.status')?.rawText||'Ongoing',
                        latestChap:parseInt(result.childNodes[1].childNodes[1].childNodes[0].rawText.split(" ")[1]),
                    };
                    payload.push(aux);
                }
                return payload
            } 
    }
    /**
     * 
     * @param {String} query 
     * @returns {Array<Manga>}
     * @typedef {Object} Manga
     * @property {Link} link - Manga Link
     * @property {String} title - Manga Title
     * @property {Link} img - Image Link
     * @property {Number} latestChap - Latest Chapter Number
     * @typedef {String} Link
     */
    async SearchByTag(query, ammount=5)
    {
        return await fetch(this.BaseLink+'genres/'+query, {timeout:this.timeout})
            .then(handleResponse)
            .then(handleData)
            .catch(handleError);
            function handleResponse(response) 
            {
                return response.text();
            }
            function handleError(error) 
            {
                return error;
            }
            function handleData(data) 
            {
                data = data.split('<div class="listupd">')[1].split('<div class="pagination">')[0]
                const document = parse(data);
                var payload = [];
                var results = document.querySelectorAll('a')
                var limit = results.length<ammount?results.length:ammount;
                for(var i =0;i<limit; i++)
                {
                    const result = results[i];
                    var aux = {
                        link:result.rawAttrs.split('"')[1],
                        title:decodeHTML(result.rawAttrs.split('"')[3]),
                        img:result.querySelectorAll('.limit > img')[0].rawAttrs.split('data-src="')[1].split('"')[0],
                        status:result.querySelector('.status')?.rawText||'Ongoing',
                        latestChap:parseInt(result.childNodes[1].childNodes[1].childNodes[0].rawText.split(" ")[1]),
                    };
                    payload.push(aux);
                }
                return payload
            } 
    }

    /**
     * 
     * @param {String} name Manga/Manwha Name
     * @param {Link} link Manga url (
     * @returns {Array<Chapter>} - Chapters Array
     * @typedef {Object} Chapter
     * @property {Number} num - Chapter Number
     * @property {String} link - Chapter Link
     * @property {String} date - Chapter Release Date
     * @typedef {String} Link
     * @pattern ^(https?:\/\/)?([\w\d.-]+)\.([a-z]{2,})(:[0-9]+)?(\/\S*)?$
    */
    async ChapterList(link, name)
    {
        return await fetch(link, {timeout:this.timeout})
        .then(handleResponse)
        .then(handleData)
        .catch(handleError);
        function handleResponse(response) 
        {
            return response.text();
        }
        function handleError(error) 
        {
            return error;
        }
        function handleData(data) 
        {
            
            const document = parse(data);
            const chapterlist = document.querySelectorAll('ul')[2];
            const chapters = parse(chapterlist).querySelectorAll('li');
            var payload = [];
            try {
                for(var chapter of chapters)
                {
                    var aux = {
                        num:parseInt(chapter.rawAttrs.split('"')[1]),
                        link:chapter.childNodes[0].childNodes[0].childNodes[1].rawAttrs.split('"')[1],
                        date:chapter.childNodes[0].childNodes[0].childNodes[1].childNodes[3].rawText,
                        
                    };
                    payload.push(aux);
                }
            } catch (error) {
                throw new Error('This manga should be called by url', error);
            }
            return payload
        } 
    }
    /**
     * 
     * @param {Link} Link Chapter Link
     * @returns {ChapterList}
     * @typedef {Obejct} ChapterList 
     * @property {Array<Image>} List
     * @property {Link} mangaLink - Manga Link
     * @typedef {String} Image - Image link
     * @typedef {String} Link
     * @pattern ^(https?:\/\/)?([\w\d.-]+)\.([a-z]{2,})(:[0-9]+)?(\/\S*)?$

     */
    async Chapter(Link)
    {
        return await fetch(Link, {timeout:this.timeout})
        .then(handleResponse)
        .then(handleData)
        .catch(handleError);
        function handleResponse(response) 
        {
            return response.text();
        }
        function handleError(error) 
        {
            return error;
        }
        function handleData(data) 
        {
            const document = parse(data);
            var List = [];
            let mangaLink = document.querySelectorAll('.allc')[0].querySelector('a')._rawAttrs.href;
            for(var image of document.querySelectorAll('p')[1].childNodes)
            {
                if(image.rawAttrs)
                {
                    let index = image.rawAttrs.split('"').findIndex(el => el.includes('http'));
                    List.push(image.rawAttrs.split('"')[index].replace(/\n/g, ''));
                }
            }
            return {List, mangaLink}
        }
    }
   /**
     * 
     * @param {String} Title 
     * @returns {Manga}
     * @typedef {Object} Manga
     * @property {Link} Link - Manga Link
     * @property {Link} img - Image Link
     * @property {String} description - Latest Chapter Number
     * @property {String} Type - Manga Type
     * @property {String} Released - Year of Release
     * @property {String} Author - Author's name
     * @property {String} Artist - Artist Team
     * @property {String} Serialization - Serialization Company
     * @property {Number} latestChap - Latest Chap number
     * @property {Array<String>} tags - Manga Tags
     * @typedef {String} Link
     */
    async GetManga(Link, title)
    {
        const auxTitle = title;
        return await fetch(Link, {timeout:this.timeout})
        .then(handleResponse)
        .then(handleData)
        .catch(handleError);
        function handleResponse(response) 
        {
            return response.text();
        }
        function handleError(error) 
        {
            return error;
        }
        function handleData(data) 
        {            
            
            const parsed = parse(data)
            let description = parsed.querySelectorAll('.entry-content-single')[0].innerText
            description = decodeHTML(description);
            if(description.split('/>').length>1) description = description.split('/>')[1]
            const img = parsed.querySelectorAll('img')[1].rawAttrs.split('src="')[1].split('"')[0].includes('data:')? parsed.querySelectorAll('img')[1].rawAttrs.split('data-src="')[1].split('"')[0]:parsed.querySelectorAll('img')[1].rawAttrs.split('src="')[1].split('"')[0];
            let table = parsed.querySelectorAll('.infotable')[0].childNodes[0].structuredText.split('\n');
            let tags = parsed.querySelectorAll('.seriestugenre')[0].structuredText.split('\n')[0].split(' ');
            let latestChap = parseInt(parsed.querySelectorAll('.epcurlast')[0].rawText.split(' ')[1])
            table.splice(-6);
            const aux = {};
            for (let i = 0; i < table.length; i += 2) {
                const key = table[i].trim();
                aux[key] = table[i + 1].trim();
            }

            return {description, img, ...aux, tags, title:auxTitle, latestChap}

        }     
    }
    /**
     * 
     * @param {String} title Manga Title
     * @returns {Boolean} 
     */
    async hasTitle(title)
    {
        const Search = await this.Search(title);
        if(!Array.isArray(Search)) return false
        return Search.filter(Manga => {return Manga.title === title})[0];
    }
}