import * as vscode from 'vscode';
import * as fspath from 'path';
import * as fs from 'fs';

import { AbsPath, opeParam } from '../global';
import { PrjInfo, RawPrjInfo } from '../global/prjInfo';
import { HdlLangID } from '../global/enum';
import { hdlFile, hdlPath } from '../hdlFs';
import { getIconConfig } from '../hdlFs/icons';
import { getLanguageId } from '../hdlFs/file';

type MissPathType = { path?: string };
type LibPickItem = vscode.QuickPickItem & MissPathType;

class LibPick {
    commonPath: AbsPath;
    customPath: AbsPath;
    commonQuickPickItem: LibPickItem;
    customQuickPickItem: LibPickItem;
    rootItems: LibPickItem[];
    backQuickPickItem: LibPickItem;
    curPath: AbsPath;
    selectedQuickPickItem: LibPickItem | undefined;

    constructor () {
        this.commonPath = opeParam.prjInfo.libCommonPath;
        this.customPath = opeParam.prjInfo.libCustomPath;
        if (!this.customPath) {
            this.customPath = 'no custom path is defined, see Prj->Lib->Custom->Path';
        }
        
        this.commonQuickPickItem = {
            label: "$(libpick-common) common", 
            description: 'common library provided by us',
            detail: 'current path: ' + this.commonPath,
            path: this.commonPath,
            buttons: [{iconPath: getIconConfig('import'), tooltip: 'import everything in common'}]
        };

        this.customQuickPickItem = {
            label: "$(libpick-custom) custom", 
            description: 'custom library by yourself',
            detail: 'current path: ' + this.customPath,
            path: this.customPath,
            buttons: [{iconPath: getIconConfig('import'), tooltip: 'import everything in custom'}]
        };

        this.rootItems = [
            this.commonQuickPickItem,
            this.customQuickPickItem
        ];

        this.backQuickPickItem = {
            label: '...', 
            description: 'return'
        };

        this.curPath = '';
    }

    getPathIcon(path: AbsPath): string {
        let prompt;
        if (hdlFile.isFile(path)) {
            const langID = hdlFile.getLanguageId(path);
            if (langID === HdlLangID.Vhdl) {
                prompt = 'vhdl';
            } else if (langID === HdlLangID.Verilog ||
                       langID === HdlLangID.SystemVerilog) {
                prompt = 'verilog';
            } else {
                prompt = 'unknown';
            }
        } else {
            prompt = 'folder';
        }
        return `$(libpick-${prompt})`;
    }

    private getReadmeText(path: AbsPath, fileName: string): string | undefined {
        const allowReadmeFile = ['readme.md', 'README.md', 'readme', 'README', 'readme.txt']
        for (const readmeFile of allowReadmeFile) {
            const mdpath = hdlPath.join(path, fileName, readmeFile);
            if (fs.existsSync(mdpath)) {
                return hdlFile.readFile(mdpath);
            }
        }

        return undefined;
    }

    private makeQuickPickItemsByPath(path: AbsPath, back: boolean=true): LibPickItem[] {
        const items: LibPickItem[] = [];
        if (!hdlPath.exist(path)) {
            return items;
        }
        if (back) {
            items.push(this.backQuickPickItem);
        }

        for (const fileName of fs.readdirSync(path)) {            
            const filePath = hdlPath.join(path, fileName);
            if (hdlFile.isFile(filePath)) {
                const fileLangId = getLanguageId(filePath);
                if (fileLangId === HdlLangID.Unknown) {
                    // 不是 hdl 直接跳过
                    continue;
                }

                const themeIcon = this.getPathIcon(filePath);
                const label = themeIcon + " " + fileName;
                const buttons = [{iconPath: getIconConfig('import'), tooltip: 'import everything in ' + fileName}];
                items.push({label, description: '', path: filePath, buttons});
            } else if (hdlFile.isDir(filePath)) {
                if (['.git', '.github', '.vscode'].includes(fileName)) {
                    continue;
                }
                const themeIcon = this.getPathIcon(filePath);
                const label = themeIcon + " " + fileName;
                // 寻找 fileName 下的 readme，fileName 在这里是一个 文件夹
                const mdText = this.getReadmeText(path, fileName);
                const description = mdText ? mdText : '';
                const buttons = [{iconPath: getIconConfig('import'), tooltip: 'import everything in ' + fileName}];
                items.push({label, description, path: filePath, buttons});
            }

        }
        return items;
    }

    private provideQuickPickItem(item?: LibPickItem) {
        if (!item) {
            return this.rootItems;
        } else if (item === this.backQuickPickItem) {
            if ((this.curPath === this.commonPath) || 
                (this.curPath === this.customPath)) {
                return this.rootItems;
            } else {
                // rollback the current path
                this.curPath = fspath.dirname(this.curPath);
            }
        } else if (item === this.commonQuickPickItem) {
            this.curPath = this.commonPath;
        } else if (item === this.customQuickPickItem) {
            this.curPath = this.customPath;
        } else {
            const label = item.label;
            const fileName = label.replace(/\$\([\s\S]*\)/, '').trim();
            this.curPath = hdlPath.join(this.curPath, fileName);
        }

        return this.makeQuickPickItemsByPath(this.curPath);
    }

    async pickItems() {
        const pickWidget = vscode.window.createQuickPick<LibPickItem>();
        
        pickWidget.placeholder = 'pick the library';
        pickWidget.items = this.provideQuickPickItem();
        
        pickWidget.onDidChangeSelection(items => {
            if (items[0]) {
                this.selectedQuickPickItem = items[0];
            }
        });

        pickWidget.onDidAccept(() => {
            if (this.selectedQuickPickItem) {
                const childernItems = this.provideQuickPickItem(this.selectedQuickPickItem);
                if (childernItems && childernItems.length > 0) {
                    pickWidget.items = childernItems;
                }
            }
        });

        pickWidget.onDidTriggerItemButton(event => {
            const selectedPath = event.item.path;

            if (selectedPath && hdlPath.exist(selectedPath)) {
                const userPrjInfo = opeParam.getUserPrjInfo();
                
                if (selectedPath.includes(this.commonQuickPickItem.path!)) {
                    // this is a module import from common, use relative path
                    const relPath = selectedPath.replace(this.commonQuickPickItem.path + '/', '');
                    userPrjInfo.appendLibraryCommonPath(relPath);
                } else {
                    // this is a module import from custom, use absolute path
                    const relPath = selectedPath.replace(this.customQuickPickItem.path + '/', '');
                    userPrjInfo.appendLibraryCustomPath(relPath);
                }

                // acquire raw and replace it
                const rawUserPrjInfo = opeParam.getRawUserPrjInfo();
                rawUserPrjInfo.library = userPrjInfo.library;
                hdlFile.writeJSON(opeParam.propertyJsonPath, rawUserPrjInfo);
            }
        });

        pickWidget.show();
    }
}

async function pickLibrary() {
    const picker = new LibPick();
    await picker.pickItems();
}

export {
    LibPick,
    LibPickItem,
    pickLibrary
};