import type { Phonetic, Meaning, Definition, OfflineDic } from './types';
import type APIManager from 'src/apiManager';
import { normalizePath, request } from 'obsidian';
import type { DefinitionProvider, DictionaryWord } from "src/integrations/types";

export class OfflineDictionary implements DefinitionProvider {
    public name = "Offline Dictionary";
    public supportedLanguages: string[] = ["en_US", "en_GB", "cn"];
    offlineDic: Record<string, OfflineDic>
    offline = true;
    manager: APIManager;

    constructor(manager: APIManager) {
        this.manager = manager;
    }

    async requestDefinitions(query: string, lang: string): Promise<DictionaryWord> {
        const data = (await this.getOfflineDictionary())[query.toLowerCase()];
        if(!data){
            return Promise.reject("Word doesnt exist in Offline Dictionary");
        }
        const phonetics: Phonetic[] = [];
        data.readings.forEach(element => {
            phonetics.push({text: element});
        });
        const meanings: Meaning[]= [];
        data.defs.forEach(element => {
            const definition: Definition[] = [];
            definition.push({
                definition: lang === "cn" ? element.def_cn : element.def_en,
                example: lang === "cn" ? element.ext?.first()?.ext_cn : element.ext?.first()?.ext_en ?? ""
            });
            meanings.push({
                partOfSpeech: lang === "cn" ? element.pos_cn : element.pos_en,
                definitions: definition
            });
        });
        const dictionaryWord: DictionaryWord = {
            word: query,
            phonetics: phonetics,
            meanings: meanings
        }
        return dictionaryWord;
    }

    async getOfflineDictionary(): Promise<Record<string, OfflineDic>> {
        const { plugin } = this.manager;
        const { adapter } = plugin.app.vault;
        const path = normalizePath(`${plugin.manifest.dir}/offlineDictionary.json`);
        if (!this.offlineDic) {
            if (!await adapter.exists(path)) {
                const data = await request({ url: `https://github.com/phibr0/obsidian-dictionary/releases/download/${plugin.manifest.version}/dictionary.json` });
                await adapter.write(path, data);
            }
            this.offlineDic = JSON.parse(await adapter.read(path));
        }
        return this.offlineDic;
    }

}