const mangayomiSources = [{
    "name": "Animeonsen",
    "langs": ["en", "ja"],
    "baseUrl": "https://www.animeonsen.xyz",
    "apiUrl": "https://api.animeonsen.xyz",
    "iconUrl": "https://www.google.com/s2/favicons?sz=256&domain=https://www.animeonsen.xyz",
    "typeSource": "single",
    "itemType": 1,
    "version": "1.0.0",
    "pkgPath": "anime/src/all/animeonsen.js"
}];

class DefaultExtension extends MProvider {
    constructor() {
        super();
        this.client = new Client();
    }

    getPreference(key) {
        return new SharedPreferences().get(key);
    }

    async getToken() {
        const preferences = new SharedPreferences();
        var token_ts = parseInt(preferences.getString("animeosen_token_expiry_at", "0"))
        var now_ts = parseInt(new Date().getTime() / 1000);

        // token lasts for 7days but still checking after 6days
        if (now_ts - token_ts > 60 * 60 * 24 * 6) {
            var tokenBody = {
                client_id: "f296be26-28b5-4358-b5a1-6259575e23b7",
                client_secret: "349038c4157d0480784753841217270c3c5b35f4281eaee029de21cb04084235",
                grant_type: "client_credentials"
            }
            var res = await this.client.post("https://auth.animeonsen.xyz/oauth/token", {}, tokenBody)
            res = JSON.parse(res.body)
            var token = res.access_token
            preferences.setString("animeosen_token", token);
            preferences.setString("animeosen_token_expiry_at", "" + now_ts);
            return token
        } else {
            return preferences.getString("animeosen_token", "");

        }
    }

    async getHeaders(slug) {
        var brToken = ""
        if (slug.endsWith("/search")) {
            brToken = "0e36d0275d16b40d7cf153634df78bc229320d073f565db2aaf6d027e0c30b13"
        }
        else {
            brToken = await this.getToken()
        }

        return {
            'Authorization': `Bearer ${brToken}`,
            'content-type': "application/json"
        }
    }

    async request(slug, body = {}) {

        var headers = await this.getHeaders(slug)

        if (slug.endsWith("/search")) {

            var api = `https://search.animeonsen.xyz${slug}`
            var res = await this.client.post(api, headers, body)
            return JSON.parse(res.body)
        }
        var api = `${this.source.apiUrl}/v4/content${slug}`
        var res = await this.client.get(api, headers)
        return JSON.parse(res.body)
    }

    animeContent(anime, pref_name, imgRes) {
        var name_eng = anime.content_title_en
        var name_jp = anime.content_title
        var name = pref_name == "jpn" ? name_jp : name_eng;
        var link = anime.content_id
        var imageUrl = `${this.source.apiUrl}/v4/image/${imgRes}/${link}`
        return { name, imageUrl, link };
    }

    async getHome(page) {
        var limit = 20
        var start = (page - 1) * limit;

        var slug = `/index?start=${start}&limit=${limit}`
        var res = await this.request(slug)

        var pref_name = this.getPreference("animeonsen__pref_title_lang")
        var imgRes = this.getPreference("animeonsen__pref_img_res_1")

        var hasNextPage = res.cursor.next[0]
        var list = []
        for (var anime of res.content) {
            list.push(this.animeContent(anime, pref_name, imgRes));
        }
        return { list, hasNextPage }
    }

    async getPopular(page) {
        return await this.getHome(page)
    }
    get supportsLatest() {
        throw new Error("supportsLatest not implemented");
    }

    
    async search(query, page, filters) {
        var slug = "/indexes/content/search"

        var limit = 30;
        var offset = (page - 1) * limit;
        var nextOffset = offset + limit;

        var params = { limit, offset, q: query };

        var res = await this.request(slug, params);

        var estimatedTotalHits = res.estimatedTotalHits
        var hasNextPage = estimatedTotalHits > nextOffset;

        var list = []
        var hits = res.hits
        var pref_name = this.getPreference("animeonsen__pref_title_lang")
        var imgRes = this.getPreference("animeonsen__pref_img_res_1")
        if (hits.length > 0) {
            for (var anime of hits) {
                list.push(this.animeContent(anime, pref_name, imgRes));
            }
        }
        return { list, hasNextPage }
    }

    statusCode(status) {
        return {
            "currently_airing": 0,
            "finished_airing": 1,
        }[status] ?? 5;
    }

    async getDetail(url) {
        var link = `${this.source.baseUrl}/details/${url}`
        var detailsApiSlug = `/${url}/extensive`
        var animeDetails = await this.request(detailsApiSlug);
        
        var pref_name = this.getPreference("animeonsen_pref_ep_title_lang")
        var imgRes = this.getPreference("animeonsen__pref_img_res_1")

        var name_eng = animeDetails.content_title_en
        var name_jp = animeDetails.content_title
        var name = pref_name == "jpn" ? name_jp : name_eng;
        var link = animeDetails.content_id
        var imageUrl = `${this.source.apiUrl}/v4/image/${imgRes}/${link}`
        var is_movie = animeDetails.is_movie

        var mal_data = animeDetails.mal_data
        var description = mal_data.synopsis
        var genre = []
        mal_data.genres.forEach(g => genre.push(g.name))
        var status = this.statusCode(mal_data.status);

        var chapters = [];
        var episodeAPISlug = `/${url}/episodes`
        var episodeDetails = await this.request(episodeAPISlug);
        
        Object.keys(episodeDetails).forEach(ep => {
            var ep_data = episodeDetails[ep]

            var ep_name_eng = ep_data.contentTitle_episode_en
            var ep_name_jp = ep_data.contentTitle_episode_jp
            var ep_name = pref_name == "jpn" ? ep_name_jp : ep_name_eng;

            chapters.push({
                name:`E${ep}: ${ep_name}`,
                url: `/${url}/video/${ep}`,
            })
        })

        chapters.reverse()
        return { name, imageUrl, status, description, genre,link, chapters }
    }

    // For anime episode video list
    async getVideoList(url) {
        var streamDetails = await this.request(url);
        var streamData = streamDetails.uri

        var streams = [
            {
                quality:`Default (720p)`,
                url: streamData.stream,
                originalUrl: streamData.stream
            }
        ];

        var subtitles = [];
        var subData = streamDetails.subtitles;
        Object.keys(subData).forEach(sub => {
            subtitles.push({
                label:sub,
                file: subData[url]
            })
        });

        streams[0].subtitles = subtitles

        return streams
    }
   
    getSourcePreferences() {
        return [{
            key: 'animeonsen__pref_title_lang',
            listPreference: {
                title: 'Preferred title language',
                summary: '',
                valueIndex: 0,
                entries: ["Japenese", "English"],
                entryValues: ["jpn", "en"]
            }
        }, {
            key: 'animeonsen_pref_ep_title_lang',
            listPreference: {
                title: 'Preferred episode title language',
                summary: '',
                valueIndex: 1,
                entries: ["Japenese", "English"],
                entryValues: ["jpn", "en"]
            }
        },{
            key: 'animeonsen__pref_img_res_1',
            listPreference: {
                title: 'Preferred image resolution',
                summary: '',
                valueIndex: 1,
                entries: ["Low", "Medium", "High"],
                entryValues: ["210x300", "420x600", "840x1200"]
            }
        }];
    }
}
