"use strict";
function init(modules) {
    var projectHostMap = new WeakMap();
    var ng = modules.typescript["ng_service"];
    if (ng == null || modules.typescript["skipNg"])
        return;
    var util = modules.typescript["ideUtil"];
    var versionNumbers = util.parseNumbersInVersion(modules.typescript.version);
    var is240OrMore = util.isVersionMoreOrEqual(versionNumbers, 2, 4, 0);
    if (!is240OrMore)
        return;
    function create(info) {
        var project = info.project;
        var serviceHost = new ng.TypeScriptServiceHost(info.languageServiceHost, info.languageService);
        var ls = ng.createLanguageService(serviceHost);
        serviceHost.setSite(ls);
        projectHostMap.set(info.project, serviceHost);
        var proxy = Object.create(null);
        var oldLS = info.languageService;
        var _loop_1 = function (k) {
            proxy[k] = function () {
                return oldLS[k].apply(oldLS, arguments);
            };
        };
        for (var k in oldLS) {
            _loop_1(k);
        }
        proxy.getSuggestionDiagnostics = function (fileName) {
            var isHtml = isHtmlFile(fileName);
            return isHtml ? [] : oldLS.getSuggestionDiagnostics(fileName);
        };
        proxy.getSyntacticDiagnostics = function (fileName) {
            var isHtml = isHtmlFile(fileName);
            return isHtml ? [] : oldLS.getSyntacticDiagnostics(fileName);
        };
        proxy.getSemanticDiagnostics = function (fileName) {
            var isHtml = isHtmlFile(fileName);
            var result = isHtml ? [] : oldLS.getSemanticDiagnostics(fileName);
            var base = result || [];
            tryOperation('get diagnostics', function () {
                if (isHtml) {
                    var isIncluded = isIncludeToExternalFiles(fileName);
                    if (!isIncluded)
                        return;
                }
                info.project.projectService.logger.info("Computing Angular semantic diagnostics...");
                var ours = ls.getDiagnostics(fileName);
                if (ours && ours.length) {
                    var file_1 = oldLS.getProgram().getSourceFile(fileName);
                    base = base.concat(ours.map(function (d) { return diagnosticToDiagnostic(d, file_1); }));
                    info.project.projectService.logger.info("End computing semantic diagnostics... " + ours.length + " ");
                }
                else {
                    info.project.projectService.logger.info("No diagnostics, used based " + base.length + " ");
                }
            });
            return base;
        };
        var isIncludeToExternalFiles = function (fileName) {
            if (info.project.projectKind == modules.typescript.server.ProjectKind.Inferred) {
                return false;
            }
            var externalFiles = getExternalFiles(info.project);
            var isIncluded = false;
            for (var _i = 0, externalFiles_1 = externalFiles; _i < externalFiles_1.length; _i++) {
                var file = externalFiles_1[_i];
                if (file == fileName) {
                    isIncluded = true;
                }
            }
            return isIncluded;
        };
        proxy.getCompletionsAtPosition = function (fileName, position) {
            var isHtml = isHtmlFile(fileName);
            var result = isHtml ? null : oldLS.getCompletionsAtPosition(fileName, position);
            var base = result || {
                isGlobalCompletion: false,
                isMemberCompletion: false,
                isNewIdentifierLocation: false,
                entries: []
            };
            tryOperation('get completions', function () {
                if (isHtml) {
                    var isIncluded = isIncludeToExternalFiles(fileName);
                    if (!isIncluded)
                        return base;
                }
                var results = ls.getCompletionsAt(fileName, position);
                if (results && results.length) {
                    if (base === undefined) {
                        base = {
                            isGlobalCompletion: false,
                            isMemberCompletion: false,
                            isNewIdentifierLocation: false,
                            entries: []
                        };
                    }
                    for (var _i = 0, results_1 = results; _i < results_1.length; _i++) {
                        var entry = results_1[_i];
                        base.entries.push(completionToEntry(entry));
                    }
                }
            });
            return base;
        };
        function tryOperation(attempting, callback) {
            try {
                return callback();
            }
            catch (e) {
                info.project.projectService.logger.info("Failed to " + attempting + ": " + e.toString());
                info.project.projectService.logger.info("Stack trace: " + e.stack);
                return null;
            }
        }
        function isHtmlFile(fileName) {
            return fileName.toLowerCase().endsWith(".html");
        }
        return proxy;
    }
    function getExternalFiles(project) {
        var host = projectHostMap.get(project);
        if (host && project.program) {
            return host.getTemplateReferences();
        }
    }
    function completionToEntry(c) {
        return { kind: c.kind, name: c.name, sortText: c.sort, kindModifiers: '' };
    }
    function diagnosticToDiagnostic(d, file) {
        var result = {
            file: file,
            start: d.span.start,
            length: d.span.end - d.span.start,
            messageText: d.message,
            category: modules.typescript.DiagnosticCategory.Error,
            code: 0,
            source: 'ng'
        };
        return result;
    }
    return { create: create, getExternalFiles: getExternalFiles };
}
module.exports = init;
