import { Atom } from "@web-atoms/core/dist/Atom";
import { BindableProperty } from "@web-atoms/core/dist/core/BindableProperty";
import { UMD } from "@web-atoms/core/dist/core/types";
import DISingleton from "@web-atoms/core/dist/di/DISingleton";
import { BaseService } from "@web-atoms/core/dist/services/http/RestService";
import { AtomControl } from "@web-atoms/core/dist/web/controls/AtomControl";
import WebApp from "@web-atoms/core/dist/web/WebApp";
import PartialPage from "./PartialPage";

@DISingleton()
class MDService extends BaseService {

    public async getUrl(url: string): Promise<string> {
        const b = this.app.createBusyIndicator();
        try {
            const a = await this.ajax(url, { method: "GET" });
            return a.responseText;
        } finally {
            b.dispose();
        }
    }

}

export default class CodeView extends PartialPage {

    public src: string = null;

    public code: string = null;

    public language: string = null;

    public async init() {

        let src = this.src;
        if(!this.code && src) {
            if (/^\./.test(src)) {
                src = src.replace("/dist/", "/src/");
            }
            this.language = this.getLanguage(src);
            this.code = await this.resolve(MDService).getUrl(src);
        }

        if(this.code) {
            this.app.runAsync(() => this.generate());
        }
    }


    private async generate(): Promise<void> {

        const app = this.app as WebApp;
        app.installStyleSheet("https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/styles/github.min.css");
        const highlight = await UMD.import<any>("https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/lib/index.min.js");

        const text = this.code;

        this.removeAllChildren(this.element);
        const pre = document.createElement("pre");
        const code = document.createElement("code");
        code.textContent = text
            .split("\n")
            .map((s) => {
                while (s.endsWith("\r")) {
                    s = s.substring(0, s.length - 1);
                }
                s = s.replace(/\t/g, "   ");
                return s;
            })
            .join("\n");

        const language = this.language;

        pre.classList.add(language);
        pre.classList.add(`language-${language}`);
        pre.appendChild(code);

        highlight.highlightBlock(pre);
        this.element.appendChild(pre);
    }

    private getLanguage(path: string): string {
        if (/\.tsx$/gi.test(path)) {
            return "typescript";
        }
        if (/\.ts$/gi.test(path)) {
            return "typescript";
        }
        if (/\.js$/gi.test(path)) {
            return "javascript";
        }
        if (/\.json$/gi.test(path)) {
            return "json";
        }
        return "plain";
    }

}
