import { readAll } from "https://deno.land/std@0.143.0/streams/mod.ts";
import * as log from "https://deno.land/std@0.143.0/log/mod.ts";
import { WriterHandler } from "https://deno.land/std@0.143.0/log/handlers.ts";
import * as Eta from "https://deno.land/x/eta@v1.12.3/mod.ts";
import { Issue } from "./githubType.ts";

import testcaseData from "./testcases.json" assert { type: "json"};

type Testcase = {
    id: number,
    subId: number | null,
    content: string,
    procedure: string,
    testData: string| null,
    expected: string,
    actual: string,
    pass: boolean
}
const testcases = testcaseData as Testcase[];

class StderrHandler extends WriterHandler {
    protected _writer: Deno.Writer;
    #encoder: TextEncoder;
    constructor(levelName: log.LevelName, options: log.HandlerOptions = {}){
        super(levelName, options);
        this.#encoder = new TextEncoder();
        this._writer = Deno.stderr;
    }
    log(msg: string): void {
        const encoded = this.#encoder.encode(msg);
        Deno.stderr.writeSync(encoded);
    }
}

interface Book {
    sections: BookItem[];
}
type Separator = "Separator";
//type PartTitle = ;
type BookItem = Separator | {
    Chapter: Chapter;
}

interface Chapter {
    name: string;
    content: string;
    /** section number */
    number?: number[];
    sub_items: BookItem[];
    path?: string;
    source_path?: string;
    parent_names: string[];
}

if (import.meta.main) {
    await log.setup({
        handlers: {
            console: new StderrHandler("INFO", {
                formatter: "{levelName} {msg}",
            }),
        },
        loggers: {
            default: {
                level: "INFO",
                handlers: ["console"],
            }
        }
    }
    );
    main(Deno.args);
}

async function getIssues(){
    const issue_path = "cache/issues.json";
    const c = await Deno.readTextFile(issue_path);
    const issues = JSON.parse(c) as Issue[];
    issues.sort((a, b) => a.number - b.number);
    return issues;
}

function toHeadId(name: string){
    return name.replaceAll(/[^A-Za-z\s0-9]/gi,"").toLocaleLowerCase().replaceAll(" ","-");
}

async function getCurrentGitHash() {
    const res = await Deno.run({cmd:["git", "rev-parse", "HEAD"], stdout:"piped"});
    const hash = new TextDecoder().decode(await res.output()).trim();
    res.close();
    return hash;;
}

async function main(args: string[]) {
    if (args.length > 1) {
        //log.info(`args: ${JSON.stringify(args)}`);
        if (args[0] === "supports") {
            Deno.exit(0);
        }
    }
    const issues = await getIssues();
    const table = new Map();
    issues.forEach((x)=>{
        const category = x.title.split(":")[0];
        if(!category) return;
        let c = table.get(category)
        if(!c){
            c = [];
            table.set(category,c);
        }
        c.push(x);
    });
    const gitHash = await getCurrentGitHash();
    
    log.info(`start\n`);
    const data = await readAll(Deno.stdin);
    const jsonText = new TextDecoder().decode(data);
    await Deno.writeTextFile("log.json", jsonText);
    const [context, book] = JSON.parse(jsonText) as [any, Book];
    book.sections.forEach(x=>{
        if(x === "Separator"){
            //skip
        }
        else {
            x.Chapter.content = Eta.render(x.Chapter.content, {
                issues: issues,
                table: table,
                gitHash: gitHash,
                toHeadId: toHeadId,
                testcases: testcases
            }) as string;
        }
    })
    //Deno.stderr.writeSync(new TextEncoder().encode(`context: ${JSON.stringify(context)}\n`));
    console.log(JSON.stringify(book));
}