import * as vscode from 'vscode';
import * as path from 'path';
import * as fs from 'fs';
import { generateTkinterCode } from './generator';
import { parsePythonToGrapes } from './pythonParser';

export class TkinterEditorProvider implements vscode.CustomTextEditorProvider {

    public static readonly viewType = 'tkinter-designer.editor';

    public static register(context: vscode.ExtensionContext): vscode.Disposable {
        const provider = new TkinterEditorProvider(context);
        return vscode.window.registerCustomEditorProvider(TkinterEditorProvider.viewType, provider);
    }

    constructor(
        private readonly context: vscode.ExtensionContext
    ) { }

    private isSaving = false;

    public async resolveCustomTextEditor(
        document: vscode.TextDocument,
        webviewPanel: vscode.WebviewPanel,
        _token: vscode.CancellationToken
    ): Promise<void> {
        
        webviewPanel.webview.options = {
            enableScripts: true,
            localResourceRoots: [vscode.Uri.file(path.join(this.context.extensionPath, 'media'))]
        };

        webviewPanel.webview.html = this.getHtmlForWebview(webviewPanel.webview);

        webviewPanel.webview.onDidReceiveMessage(e => {
            switch (e.type) {
                case 'request-load':
                    this.handleRequestLoad(document, webviewPanel);
                    break;
                case 'update-code':
                    this.isSaving = true;
                    this.handleSave(document, e.payload);
                    setTimeout(() => { this.isSaving = false; }, 500);
                    break;
                case 'request-import':
                    this.handleImport(webviewPanel);
                    break;
            }
        });

        const folderPath = path.dirname(document.uri.fsPath);
        const fileNameBase = path.basename(document.uri.fsPath, path.extname(document.uri.fsPath));
        const pyFilePath = path.join(folderPath, `${fileNameBase}.py`);

        const watcher = vscode.workspace.createFileSystemWatcher(pyFilePath);
        
        watcher.onDidChange(() => {
            // 
        });

        webviewPanel.onDidDispose(() => watcher.dispose());
    }

    private handleRequestLoad(document: vscode.TextDocument, panel: vscode.WebviewPanel) {
        const text = document.getText();
        let payload = {};
        try {
            if (text.trim().length > 0) payload = JSON.parse(text);
        } catch (e) { console.error(e); }
        panel.webview.postMessage({ type: 'load-data', payload: payload });
    }

    private async handleSave(document: vscode.TextDocument, jsonPayload: any) {
        const folderPath = path.dirname(document.uri.fsPath);
        const fileNameBase = path.basename(document.uri.fsPath, path.extname(document.uri.fsPath));
        const pyFilePath = path.join(folderPath, `${fileNameBase}.py`);

        const pythonCode = generateTkinterCode(jsonPayload);
        try {
            fs.writeFileSync(pyFilePath, pythonCode);
        } catch (e) {
            console.error(`Python Save error: ${e}`);
        }

        // СОХРАНЕНИЕ JSON
        const edit = new vscode.WorkspaceEdit();
        const fullRange = new vscode.Range(
            document.positionAt(0),
            document.positionAt(document.getText().length)
        );
        edit.replace(document.uri, fullRange, JSON.stringify(jsonPayload, null, 2));
        await vscode.workspace.applyEdit(edit);
        await document.save();
    }

    private async handleImport(panel: vscode.WebviewPanel) {
        const uris = await vscode.window.showOpenDialog({
            canSelectMany: false,
            openLabel: 'Import Python',
            filters: { 'Python Files': ['py'] }
        });
        if (uris && uris[0]) {
            const content = fs.readFileSync(uris[0].fsPath, 'utf-8');
            const data = parsePythonToGrapes(content);
            panel.webview.postMessage({ type: 'import-data', payload: data });
        }
    }

    private getHtmlForWebview(webview: vscode.Webview): string {
        const mediaPath = path.join(this.context.extensionPath, 'media');
        const scriptUri = webview.asWebviewUri(vscode.Uri.file(path.join(mediaPath, 'grapes.min.js')));
        const styleUri = webview.asWebviewUri(vscode.Uri.file(path.join(mediaPath, 'grapes.min.css')));
        const mainScriptUri = webview.asWebviewUri(vscode.Uri.file(path.join(mediaPath, 'main.js')));
        const fontUrl = "https://unpkg.com/grapesjs/dist/fonts/grapes.woff";

        return `<!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource} 'unsafe-inline' https:; script-src ${webview.cspSource} 'unsafe-inline' 'unsafe-eval'; font-src ${webview.cspSource} https: data:;">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <link href="${styleUri}" rel="stylesheet">
                <style>
                    html, body { height: 100%; margin: 0; overflow: hidden; } 
                    #editor { height: 100%; }
                    @font-face { font-family: 'GrapesJS'; src: url('${fontUrl}') format('woff'); font-weight: normal; font-style: normal; }
                </style>
                <title>Tkinter Designer</title>
            </head>
            <body>
                <div id="editor"></div>
                <script src="${scriptUri}"></script>
                <script src="${mainScriptUri}"></script>
            </body>
            </html>`;
    }
}