/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
import './media/referencesWidget.css';
import * as nls from '../../../nls';
import { onUnexpectedError } from '../../../base/common/errors';
import { getPathLabel } from '../../../base/common/labels';
import { Emitter } from '../../../base/common/event';
import { dispose } from '../../../base/common/lifecycle';
import { Schemas } from '../../../base/common/network';
import * as strings from '../../../base/common/strings';
import { TPromise } from '../../../base/common/winjs.base';
import { Color } from '../../../base/common/color';
import { $ } from '../../../base/browser/builder';
import * as dom from '../../../base/browser/dom';
import { Sash } from '../../../base/browser/ui/sash/sash';
import { CountBadge } from '../../../base/browser/ui/countBadge/countBadge';
import { FileLabel } from '../../../base/browser/ui/iconLabel/iconLabel';
import { optional } from '../../../platform/instantiation/common/instantiation';
import { IWorkspaceContextService } from '../../../platform/workspace/common/workspace';
import { Range } from '../../common/core/range';
import * as editorCommon from '../../common/editorCommon';
import { TextModel, ModelDecorationOptions } from '../../common/model/textModel';
import { EmbeddedCodeEditorWidget } from '../../browser/widget/embeddedCodeEditorWidget';
import { PeekViewWidget } from './peekViewWidget';
import { FileReferences, OneReference, ReferencesModel } from './referencesModel';
import { ITextModelService } from '../../common/services/resolverService';
import { registerColor, activeContrastBorder, contrastBorder } from '../../../platform/theme/common/colorRegistry';
import { registerThemingParticipant, IThemeService } from '../../../platform/theme/common/themeService';
import { attachListStyler, attachBadgeStyler } from '../../../platform/theme/common/styler';
import { IEnvironmentService } from '../../../platform/environment/common/environment';
import URI from '../../../base/common/uri';
import { TrackedRangeStickiness } from '../../common/model';
import { WorkbenchTree, WorkbenchTreeController } from '../../../platform/list/browser/listService';
import { RawContextKey } from '../../../platform/contextkey/common/contextkey';
import { ClickBehavior } from '../../../base/parts/tree/browser/treeDefaults';
var DecorationsManager = /** @class */ (function () {
    function DecorationsManager(_editor, _model) {
        var _this = this;
        this._editor = _editor;
        this._model = _model;
        this._decorations = new Map();
        this._decorationIgnoreSet = new Set();
        this._callOnDispose = [];
        this._callOnModelChange = [];
        this._callOnDispose.push(this._editor.onDidChangeModel(function () { return _this._onModelChanged(); }));
        this._onModelChanged();
    }
    DecorationsManager.prototype.dispose = function () {
        this._callOnModelChange = dispose(this._callOnModelChange);
        this._callOnDispose = dispose(this._callOnDispose);
        this.removeDecorations();
    };
    DecorationsManager.prototype._onModelChanged = function () {
        this._callOnModelChange = dispose(this._callOnModelChange);
        var model = this._editor.getModel();
        if (model) {
            for (var _i = 0, _a = this._model.groups; _i < _a.length; _i++) {
                var ref = _a[_i];
                if (ref.uri.toString() === model.uri.toString()) {
                    this._addDecorations(ref);
                    return;
                }
            }
        }
    };
    DecorationsManager.prototype._addDecorations = function (reference) {
        var _this = this;
        this._callOnModelChange.push(this._editor.getModel().onDidChangeDecorations(function (event) { return _this._onDecorationChanged(); }));
        this._editor.changeDecorations(function (accessor) {
            var newDecorations = [];
            var newDecorationsActualIndex = [];
            for (var i = 0, len = reference.children.length; i < len; i++) {
                var oneReference = reference.children[i];
                if (_this._decorationIgnoreSet.has(oneReference.id)) {
                    continue;
                }
                newDecorations.push({
                    range: oneReference.range,
                    options: DecorationsManager.DecorationOptions
                });
                newDecorationsActualIndex.push(i);
            }
            var decorations = accessor.deltaDecorations([], newDecorations);
            for (var i = 0; i < decorations.length; i++) {
                _this._decorations.set(decorations[i], reference.children[newDecorationsActualIndex[i]]);
            }
        });
    };
    DecorationsManager.prototype._onDecorationChanged = function () {
        var _this = this;
        var toRemove = [];
        this._decorations.forEach(function (reference, decorationId) {
            var newRange = _this._editor.getModel().getDecorationRange(decorationId);
            if (!newRange) {
                return;
            }
            var ignore = false;
            if (Range.equalsRange(newRange, reference.range)) {
                return;
            }
            else if (Range.spansMultipleLines(newRange)) {
                ignore = true;
            }
            else {
                var lineLength = reference.range.endColumn - reference.range.startColumn;
                var newLineLength = newRange.endColumn - newRange.startColumn;
                if (lineLength !== newLineLength) {
                    ignore = true;
                }
            }
            if (ignore) {
                _this._decorationIgnoreSet.add(reference.id);
                toRemove.push(decorationId);
            }
            else {
                reference.range = newRange;
            }
        });
        this._editor.changeDecorations(function (accessor) {
            for (var i = 0, len = toRemove.length; i < len; i++) {
                _this._decorations.delete(toRemove[i]);
            }
            accessor.deltaDecorations(toRemove, []);
        });
    };
    DecorationsManager.prototype.removeDecorations = function () {
        var _this = this;
        this._editor.changeDecorations(function (accessor) {
            _this._decorations.forEach(function (value, key) {
                accessor.removeDecoration(key);
            });
            _this._decorations.clear();
        });
    };
    DecorationsManager.DecorationOptions = ModelDecorationOptions.register({
        stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
        className: 'reference-decoration'
    });
    return DecorationsManager;
}());
var DataSource = /** @class */ (function () {
    function DataSource(_textModelResolverService) {
        this._textModelResolverService = _textModelResolverService;
        //
    }
    DataSource.prototype.getId = function (tree, element) {
        if (element instanceof ReferencesModel) {
            return 'root';
        }
        else if (element instanceof FileReferences) {
            return element.id;
        }
        else if (element instanceof OneReference) {
            return element.id;
        }
        return undefined;
    };
    DataSource.prototype.hasChildren = function (tree, element) {
        if (element instanceof ReferencesModel) {
            return true;
        }
        if (element instanceof FileReferences && !element.failure) {
            return true;
        }
        return false;
    };
    DataSource.prototype.getChildren = function (tree, element) {
        if (element instanceof ReferencesModel) {
            return TPromise.as(element.groups);
        }
        else if (element instanceof FileReferences) {
            return element.resolve(this._textModelResolverService).then(function (val) {
                if (element.failure) {
                    // refresh the element on failure so that
                    // we can update its rendering
                    return tree.refresh(element).then(function () { return val.children; });
                }
                return val.children;
            });
        }
        else {
            return TPromise.as([]);
        }
    };
    DataSource.prototype.getParent = function (tree, element) {
        var result = null;
        if (element instanceof FileReferences) {
            result = element.parent;
        }
        else if (element instanceof OneReference) {
            result = element.parent;
        }
        return TPromise.as(result);
    };
    DataSource = __decorate([
        __param(0, ITextModelService)
    ], DataSource);
    return DataSource;
}());
var Controller = /** @class */ (function (_super) {
    __extends(Controller, _super);
    function Controller() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this._onDidFocus = new Emitter();
        _this.onDidFocus = _this._onDidFocus.event;
        _this._onDidSelect = new Emitter();
        _this.onDidSelect = _this._onDidSelect.event;
        _this._onDidOpenToSide = new Emitter();
        _this.onDidOpenToSide = _this._onDidOpenToSide.event;
        return _this;
    }
    Controller.prototype.onTap = function (tree, element, event) {
        if (element instanceof FileReferences) {
            event.preventDefault();
            event.stopPropagation();
            return this._expandCollapse(tree, element);
        }
        var result = _super.prototype.onTap.call(this, tree, element, event);
        this._onDidFocus.fire(element);
        return result;
    };
    Controller.prototype.onMouseDown = function (tree, element, event) {
        var isDoubleClick = event.detail === 2;
        if (event.leftButton) {
            if (element instanceof FileReferences) {
                if (this.openOnSingleClick || isDoubleClick || this.isClickOnTwistie(event)) {
                    event.preventDefault();
                    event.stopPropagation();
                    return this._expandCollapse(tree, element);
                }
            }
            var result = _super.prototype.onClick.call(this, tree, element, event);
            var openToSide = event.ctrlKey || event.metaKey || event.altKey;
            if (openToSide && (isDoubleClick || this.openOnSingleClick)) {
                this._onDidOpenToSide.fire(element);
            }
            else if (isDoubleClick) {
                this._onDidSelect.fire(element);
            }
            else if (this.openOnSingleClick) {
                this._onDidFocus.fire(element);
            }
            return result;
        }
        return false;
    };
    Controller.prototype.onClick = function (tree, element, event) {
        if (event.leftButton) {
            return false; // Already handled by onMouseDown
        }
        return _super.prototype.onClick.call(this, tree, element, event);
    };
    Controller.prototype._expandCollapse = function (tree, element) {
        if (tree.isExpanded(element)) {
            tree.collapse(element).done(null, onUnexpectedError);
        }
        else {
            tree.expand(element).done(null, onUnexpectedError);
        }
        return true;
    };
    Controller.prototype.onEscape = function (tree, event) {
        return false;
    };
    Controller.prototype.dispose = function () {
        this._onDidFocus.dispose();
        this._onDidSelect.dispose();
        this._onDidOpenToSide.dispose();
    };
    return Controller;
}(WorkbenchTreeController));
var FileReferencesTemplate = /** @class */ (function () {
    function FileReferencesTemplate(container, _contextService, _environmentService, themeService) {
        var _this = this;
        this._contextService = _contextService;
        this._environmentService = _environmentService;
        var parent = document.createElement('div');
        dom.addClass(parent, 'reference-file');
        container.appendChild(parent);
        this.file = new FileLabel(parent, URI.parse('no:file'), this._contextService, this._environmentService);
        this.badge = new CountBadge($('.count').appendTo(parent).getHTMLElement());
        var styler = attachBadgeStyler(this.badge, themeService);
        this.dispose = function () {
            _this.file.dispose();
            styler.dispose();
        };
    }
    FileReferencesTemplate.prototype.set = function (element) {
        this.file.setFile(element.uri, this._contextService, this._environmentService);
        var len = element.children.length;
        this.badge.setCount(len);
        if (element.failure) {
            this.badge.setTitleFormat(nls.localize('referencesFailre', "Failed to resolve file."));
        }
        else if (len > 1) {
            this.badge.setTitleFormat(nls.localize('referencesCount', "{0} references", len));
        }
        else {
            this.badge.setTitleFormat(nls.localize('referenceCount', "{0} reference", len));
        }
    };
    FileReferencesTemplate = __decorate([
        __param(1, IWorkspaceContextService),
        __param(2, optional(IEnvironmentService)),
        __param(3, IThemeService)
    ], FileReferencesTemplate);
    return FileReferencesTemplate;
}());
var OneReferenceTemplate = /** @class */ (function () {
    function OneReferenceTemplate(container) {
        var parent = document.createElement('div');
        this.before = document.createElement('span');
        this.inside = document.createElement('span');
        this.after = document.createElement('span');
        dom.addClass(this.inside, 'referenceMatch');
        dom.addClass(parent, 'reference');
        parent.appendChild(this.before);
        parent.appendChild(this.inside);
        parent.appendChild(this.after);
        container.appendChild(parent);
    }
    OneReferenceTemplate.prototype.set = function (element) {
        var _a = element.parent.preview.preview(element.range), before = _a.before, inside = _a.inside, after = _a.after;
        this.before.innerHTML = strings.escape(before);
        this.inside.innerHTML = strings.escape(inside);
        this.after.innerHTML = strings.escape(after);
    };
    return OneReferenceTemplate;
}());
var Renderer = /** @class */ (function () {
    function Renderer(_contextService, _themeService, _environmentService) {
        this._contextService = _contextService;
        this._themeService = _themeService;
        this._environmentService = _environmentService;
        //
    }
    Renderer.prototype.getHeight = function (tree, element) {
        return 23;
    };
    Renderer.prototype.getTemplateId = function (tree, element) {
        if (element instanceof FileReferences) {
            return Renderer._ids.FileReferences;
        }
        else if (element instanceof OneReference) {
            return Renderer._ids.OneReference;
        }
        throw element;
    };
    Renderer.prototype.renderTemplate = function (tree, templateId, container) {
        if (templateId === Renderer._ids.FileReferences) {
            return new FileReferencesTemplate(container, this._contextService, this._environmentService, this._themeService);
        }
        else if (templateId === Renderer._ids.OneReference) {
            return new OneReferenceTemplate(container);
        }
        throw templateId;
    };
    Renderer.prototype.renderElement = function (tree, element, templateId, templateData) {
        if (element instanceof FileReferences) {
            templateData.set(element);
        }
        else if (element instanceof OneReference) {
            templateData.set(element);
        }
        else {
            throw templateId;
        }
    };
    Renderer.prototype.disposeTemplate = function (tree, templateId, templateData) {
        if (templateData instanceof FileReferencesTemplate) {
            templateData.dispose();
        }
    };
    Renderer._ids = {
        FileReferences: 'FileReferences',
        OneReference: 'OneReference'
    };
    Renderer = __decorate([
        __param(0, IWorkspaceContextService),
        __param(1, IThemeService),
        __param(2, optional(IEnvironmentService))
    ], Renderer);
    return Renderer;
}());
var AriaProvider = /** @class */ (function () {
    function AriaProvider() {
    }
    AriaProvider.prototype.getAriaLabel = function (tree, element) {
        if (element instanceof FileReferences) {
            return element.getAriaMessage();
        }
        else if (element instanceof OneReference) {
            return element.getAriaMessage();
        }
        else {
            return undefined;
        }
    };
    return AriaProvider;
}());
var VSash = /** @class */ (function () {
    function VSash(container, ratio) {
        var _this = this;
        this._disposables = [];
        this._onDidChangePercentages = new Emitter();
        this._ratio = ratio;
        this._sash = new Sash(container, {
            getVerticalSashLeft: function () { return _this._width * _this._ratio; },
            getVerticalSashHeight: function () { return _this._height; }
        });
        // compute the current widget clientX postion since
        // the sash works with clientX when dragging
        var clientX;
        this._disposables.push(this._sash.onDidStart(function (e) {
            clientX = e.startX - (_this._width * _this.ratio);
        }));
        this._disposables.push(this._sash.onDidChange(function (e) {
            // compute the new position of the sash and from that
            // compute the new ratio that we are using
            var newLeft = e.currentX - clientX;
            if (newLeft > 20 && newLeft + 20 < _this._width) {
                _this._ratio = newLeft / _this._width;
                _this._sash.layout();
                _this._onDidChangePercentages.fire(_this);
            }
        }));
    }
    VSash.prototype.dispose = function () {
        this._sash.dispose();
        this._onDidChangePercentages.dispose();
        dispose(this._disposables);
    };
    Object.defineProperty(VSash.prototype, "onDidChangePercentages", {
        get: function () {
            return this._onDidChangePercentages.event;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(VSash.prototype, "width", {
        set: function (value) {
            this._width = value;
            this._sash.layout();
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(VSash.prototype, "height", {
        set: function (value) {
            this._height = value;
            this._sash.layout();
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(VSash.prototype, "percentages", {
        get: function () {
            var left = 100 * this._ratio;
            var right = 100 - left;
            return [left + "%", right + "%"];
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(VSash.prototype, "ratio", {
        get: function () {
            return this._ratio;
        },
        enumerable: true,
        configurable: true
    });
    return VSash;
}());
export var ctxReferenceWidgetSearchTreeFocused = new RawContextKey('referenceSearchTreeFocused', true);
/**
 * ZoneWidget that is shown inside the editor
 */
var ReferenceWidget = /** @class */ (function (_super) {
    __extends(ReferenceWidget, _super);
    function ReferenceWidget(editor, layoutData, _textModelResolverService, _contextService, _themeService, _instantiationService, _environmentService) {
        var _this = _super.call(this, editor, { showFrame: false, showArrow: true, isResizeable: true, isAccessible: true }) || this;
        _this.layoutData = layoutData;
        _this._textModelResolverService = _textModelResolverService;
        _this._contextService = _contextService;
        _this._themeService = _themeService;
        _this._instantiationService = _instantiationService;
        _this._environmentService = _environmentService;
        _this._disposeOnNewModel = [];
        _this._callOnDispose = [];
        _this._onDidSelectReference = new Emitter();
        _this._applyTheme(_themeService.getTheme());
        _this._callOnDispose.push(_themeService.onThemeChange(_this._applyTheme.bind(_this)));
        _this.create();
        return _this;
    }
    ReferenceWidget.prototype._applyTheme = function (theme) {
        var borderColor = theme.getColor(peekViewBorder) || Color.transparent;
        this.style({
            arrowColor: borderColor,
            frameColor: borderColor,
            headerBackgroundColor: theme.getColor(peekViewTitleBackground) || Color.transparent,
            primaryHeadingColor: theme.getColor(peekViewTitleForeground),
            secondaryHeadingColor: theme.getColor(peekViewTitleInfoForeground)
        });
    };
    ReferenceWidget.prototype.dispose = function () {
        this.setModel(null);
        this._callOnDispose = dispose(this._callOnDispose);
        dispose(this._preview, this._previewNotAvailableMessage, this._tree, this._sash, this._previewModelReference);
        _super.prototype.dispose.call(this);
    };
    Object.defineProperty(ReferenceWidget.prototype, "onDidSelectReference", {
        get: function () {
            return this._onDidSelectReference.event;
        },
        enumerable: true,
        configurable: true
    });
    ReferenceWidget.prototype.show = function (where) {
        this.editor.revealRangeInCenterIfOutsideViewport(where, 0 /* Smooth */);
        _super.prototype.show.call(this, where, this.layoutData.heightInLines || 18);
    };
    ReferenceWidget.prototype.focus = function () {
        this._tree.DOMFocus();
    };
    ReferenceWidget.prototype._onTitleClick = function (e) {
        if (this._preview && this._preview.getModel()) {
            this._onDidSelectReference.fire({
                element: this._getFocusedReference(),
                kind: e.ctrlKey || e.metaKey || e.altKey ? 'side' : 'open',
                source: 'title'
            });
        }
    };
    ReferenceWidget.prototype._fillBody = function (containerElement) {
        var _this = this;
        var container = $(containerElement);
        this.setCssClass('reference-zone-widget');
        // message pane
        container.div({ 'class': 'messages' }, function (div) {
            _this._messageContainer = div.hide();
        });
        // editor
        container.div({ 'class': 'preview inline' }, function (div) {
            var options = {
                scrollBeyondLastLine: false,
                scrollbar: {
                    verticalScrollbarSize: 14,
                    horizontal: 'auto',
                    useShadows: true,
                    verticalHasArrows: false,
                    horizontalHasArrows: false
                },
                overviewRulerLanes: 2,
                fixedOverflowWidgets: true,
                minimap: {
                    enabled: false
                }
            };
            _this._preview = _this._instantiationService.createInstance(EmbeddedCodeEditorWidget, div.getHTMLElement(), options, _this.editor);
            _this._previewContainer = div.hide();
            _this._previewNotAvailableMessage = TextModel.createFromString(nls.localize('missingPreviewMessage', "no preview available"));
        });
        // sash
        this._sash = new VSash(containerElement, this.layoutData.ratio || .8);
        this._sash.onDidChangePercentages(function () {
            var _a = _this._sash.percentages, left = _a[0], right = _a[1];
            _this._previewContainer.style({ width: left });
            _this._treeContainer.style({ width: right });
            _this._preview.layout();
            _this._tree.layout();
            _this.layoutData.ratio = _this._sash.ratio;
        });
        // tree
        container.div({ 'class': 'ref-tree inline' }, function (div) {
            var controller = _this._instantiationService.createInstance(Controller, { clickBehavior: ClickBehavior.ON_MOUSE_UP /* our controller already deals with this */ });
            _this._callOnDispose.push(controller);
            var config = {
                dataSource: _this._instantiationService.createInstance(DataSource),
                renderer: _this._instantiationService.createInstance(Renderer),
                controller: controller,
                accessibilityProvider: new AriaProvider()
            };
            var options = {
                twistiePixels: 20,
                ariaLabel: nls.localize('treeAriaLabel', "References")
            };
            _this._tree = _this._instantiationService.createInstance(WorkbenchTree, div.getHTMLElement(), config, options);
            _this._callOnDispose.push(attachListStyler(_this._tree, _this._themeService));
            ctxReferenceWidgetSearchTreeFocused.bindTo(_this._tree.contextKeyService);
            // listen on selection and focus
            var onEvent = function (element, kind) {
                if (element instanceof OneReference) {
                    if (kind === 'show') {
                        _this._revealReference(element);
                    }
                    _this._onDidSelectReference.fire({ element: element, kind: kind, source: 'tree' });
                }
            };
            _this._disposables.push(_this._tree.onDidChangeFocus(function (event) {
                if (event && event.payload && event.payload.origin === 'keyboard') {
                    onEvent(event.focus, 'show'); // only handle events from keyboard, mouse/touch is handled by other listeners below
                }
            }));
            _this._disposables.push(_this._tree.onDidChangeSelection(function (event) {
                if (event && event.payload && event.payload.origin === 'keyboard') {
                    onEvent(event.selection[0], 'goto'); // only handle events from keyboard, mouse/touch is handled by other listeners below
                }
            }));
            _this._disposables.push(controller.onDidFocus(function (element) { return onEvent(element, 'show'); }));
            _this._disposables.push(controller.onDidSelect(function (element) { return onEvent(element, 'goto'); }));
            _this._disposables.push(controller.onDidOpenToSide(function (element) { return onEvent(element, 'side'); }));
            _this._treeContainer = div.hide();
        });
    };
    ReferenceWidget.prototype._doLayoutBody = function (heightInPixel, widthInPixel) {
        _super.prototype._doLayoutBody.call(this, heightInPixel, widthInPixel);
        var height = heightInPixel + 'px';
        this._sash.height = heightInPixel;
        this._sash.width = widthInPixel;
        // set height/width
        var _a = this._sash.percentages, left = _a[0], right = _a[1];
        this._previewContainer.style({ height: height, width: left });
        this._treeContainer.style({ height: height, width: right });
        // forward
        this._tree.layout(heightInPixel);
        this._preview.layout();
        // store layout data
        this.layoutData = {
            heightInLines: this._viewZone.heightInLines,
            ratio: this._sash.ratio
        };
    };
    ReferenceWidget.prototype._onWidth = function (widthInPixel) {
        this._sash.width = widthInPixel;
        this._preview.layout();
    };
    ReferenceWidget.prototype.setSelection = function (selection) {
        var _this = this;
        return this._revealReference(selection).then(function () {
            // show in tree
            _this._tree.setSelection([selection]);
            _this._tree.setFocus(selection);
        });
    };
    ReferenceWidget.prototype.setModel = function (newModel) {
        // clean up
        this._disposeOnNewModel = dispose(this._disposeOnNewModel);
        this._model = newModel;
        if (this._model) {
            return this._onNewModel();
        }
        return undefined;
    };
    ReferenceWidget.prototype._onNewModel = function () {
        var _this = this;
        if (this._model.empty) {
            this.setTitle('');
            this._messageContainer.innerHtml(nls.localize('noResults', "No results")).show();
            return TPromise.as(void 0);
        }
        this._messageContainer.hide();
        this._decorationsManager = new DecorationsManager(this._preview, this._model);
        this._disposeOnNewModel.push(this._decorationsManager);
        // listen on model changes
        this._disposeOnNewModel.push(this._model.onDidChangeReferenceRange(function (reference) { return _this._tree.refresh(reference); }));
        // listen on editor
        this._disposeOnNewModel.push(this._preview.onMouseDown(function (e) {
            var event = e.event, target = e.target;
            if (event.detail === 2) {
                _this._onDidSelectReference.fire({
                    element: { uri: _this._getFocusedReference().uri, range: target.range },
                    kind: (event.ctrlKey || event.metaKey || event.altKey) ? 'side' : 'open',
                    source: 'editor'
                });
            }
        }));
        // make sure things are rendered
        dom.addClass(this.container, 'results-loaded');
        this._treeContainer.show();
        this._previewContainer.show();
        this._preview.layout();
        this._tree.layout();
        this.focus();
        // pick input and a reference to begin with
        var input = this._model.groups.length === 1 ? this._model.groups[0] : this._model;
        return this._tree.setInput(input);
    };
    ReferenceWidget.prototype._getFocusedReference = function () {
        var element = this._tree.getFocus();
        if (element instanceof OneReference) {
            return element;
        }
        else if (element instanceof FileReferences) {
            if (element.children.length > 0) {
                return element.children[0];
            }
        }
        return undefined;
    };
    ReferenceWidget.prototype._revealReference = function (reference) {
        var _this = this;
        // Update widget header
        if (reference.uri.scheme !== Schemas.inMemory) {
            this.setTitle(reference.name, getPathLabel(reference.directory, this._contextService, this._environmentService));
        }
        else {
            this.setTitle(nls.localize('peekView.alternateTitle', "References"));
        }
        var promise = this._textModelResolverService.createModelReference(reference.uri);
        return TPromise.join([promise, this._tree.reveal(reference)]).then(function (values) {
            var ref = values[0];
            if (!_this._model) {
                ref.dispose();
                // disposed
                return;
            }
            dispose(_this._previewModelReference);
            // show in editor
            var model = ref.object;
            if (model) {
                _this._previewModelReference = ref;
                var isSameModel = (_this._preview.getModel() === model.textEditorModel);
                _this._preview.setModel(model.textEditorModel);
                var sel = Range.lift(reference.range).collapseToStart();
                _this._preview.setSelection(sel);
                _this._preview.revealRangeInCenter(sel, isSameModel ? 0 /* Smooth */ : 1 /* Immediate */);
            }
            else {
                _this._preview.setModel(_this._previewNotAvailableMessage);
                ref.dispose();
            }
        }, onUnexpectedError);
    };
    return ReferenceWidget;
}(PeekViewWidget));
export { ReferenceWidget };
// theming
export var peekViewTitleBackground = registerColor('peekViewTitle.background', { dark: '#1E1E1E', light: '#FFFFFF', hc: '#0C141F' }, nls.localize('peekViewTitleBackground', 'Background color of the peek view title area.'));
export var peekViewTitleForeground = registerColor('peekViewTitleLabel.foreground', { dark: '#FFFFFF', light: '#333333', hc: '#FFFFFF' }, nls.localize('peekViewTitleForeground', 'Color of the peek view title.'));
export var peekViewTitleInfoForeground = registerColor('peekViewTitleDescription.foreground', { dark: '#ccccccb3', light: '#6c6c6cb3', hc: '#FFFFFF99' }, nls.localize('peekViewTitleInfoForeground', 'Color of the peek view title info.'));
export var peekViewBorder = registerColor('peekView.border', { dark: '#007acc', light: '#007acc', hc: contrastBorder }, nls.localize('peekViewBorder', 'Color of the peek view borders and arrow.'));
export var peekViewResultsBackground = registerColor('peekViewResult.background', { dark: '#252526', light: '#F3F3F3', hc: Color.black }, nls.localize('peekViewResultsBackground', 'Background color of the peek view result list.'));
export var peekViewResultsMatchForeground = registerColor('peekViewResult.lineForeground', { dark: '#bbbbbb', light: '#646465', hc: Color.white }, nls.localize('peekViewResultsMatchForeground', 'Foreground color for line nodes in the peek view result list.'));
export var peekViewResultsFileForeground = registerColor('peekViewResult.fileForeground', { dark: Color.white, light: '#1E1E1E', hc: Color.white }, nls.localize('peekViewResultsFileForeground', 'Foreground color for file nodes in the peek view result list.'));
export var peekViewResultsSelectionBackground = registerColor('peekViewResult.selectionBackground', { dark: '#3399ff33', light: '#3399ff33', hc: null }, nls.localize('peekViewResultsSelectionBackground', 'Background color of the selected entry in the peek view result list.'));
export var peekViewResultsSelectionForeground = registerColor('peekViewResult.selectionForeground', { dark: Color.white, light: '#6C6C6C', hc: Color.white }, nls.localize('peekViewResultsSelectionForeground', 'Foreground color of the selected entry in the peek view result list.'));
export var peekViewEditorBackground = registerColor('peekViewEditor.background', { dark: '#001F33', light: '#F2F8FC', hc: Color.black }, nls.localize('peekViewEditorBackground', 'Background color of the peek view editor.'));
export var peekViewEditorGutterBackground = registerColor('peekViewEditorGutter.background', { dark: peekViewEditorBackground, light: peekViewEditorBackground, hc: peekViewEditorBackground }, nls.localize('peekViewEditorGutterBackground', 'Background color of the gutter in the peek view editor.'));
export var peekViewResultsMatchHighlight = registerColor('peekViewResult.matchHighlightBackground', { dark: '#ea5c004d', light: '#ea5c004d', hc: null }, nls.localize('peekViewResultsMatchHighlight', 'Match highlight color in the peek view result list.'));
export var peekViewEditorMatchHighlight = registerColor('peekViewEditor.matchHighlightBackground', { dark: '#ff8f0099', light: '#f5d802de', hc: null }, nls.localize('peekViewEditorMatchHighlight', 'Match highlight color in the peek view editor.'));
registerThemingParticipant(function (theme, collector) {
    var findMatchHighlightColor = theme.getColor(peekViewResultsMatchHighlight);
    if (findMatchHighlightColor) {
        collector.addRule(".monaco-editor .reference-zone-widget .ref-tree .referenceMatch { background-color: " + findMatchHighlightColor + "; }");
    }
    var referenceHighlightColor = theme.getColor(peekViewEditorMatchHighlight);
    if (referenceHighlightColor) {
        collector.addRule(".monaco-editor .reference-zone-widget .preview .reference-decoration { background-color: " + referenceHighlightColor + "; }");
    }
    var hcOutline = theme.getColor(activeContrastBorder);
    if (hcOutline) {
        collector.addRule(".monaco-editor .reference-zone-widget .ref-tree .referenceMatch { border: 1px dotted " + hcOutline + "; box-sizing: border-box; }");
        collector.addRule(".monaco-editor .reference-zone-widget .preview .reference-decoration { border: 2px solid " + hcOutline + "; box-sizing: border-box; }");
    }
    var resultsBackground = theme.getColor(peekViewResultsBackground);
    if (resultsBackground) {
        collector.addRule(".monaco-editor .reference-zone-widget .ref-tree { background-color: " + resultsBackground + "; }");
    }
    var resultsMatchForeground = theme.getColor(peekViewResultsMatchForeground);
    if (resultsMatchForeground) {
        collector.addRule(".monaco-editor .reference-zone-widget .ref-tree { color: " + resultsMatchForeground + "; }");
    }
    var resultsFileForeground = theme.getColor(peekViewResultsFileForeground);
    if (resultsFileForeground) {
        collector.addRule(".monaco-editor .reference-zone-widget .ref-tree .reference-file { color: " + resultsFileForeground + "; }");
    }
    var resultsSelectedBackground = theme.getColor(peekViewResultsSelectionBackground);
    if (resultsSelectedBackground) {
        collector.addRule(".monaco-editor .reference-zone-widget .ref-tree .monaco-tree.focused .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { background-color: " + resultsSelectedBackground + "; }");
    }
    var resultsSelectedForeground = theme.getColor(peekViewResultsSelectionForeground);
    if (resultsSelectedForeground) {
        collector.addRule(".monaco-editor .reference-zone-widget .ref-tree .monaco-tree.focused .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { color: " + resultsSelectedForeground + " !important; }");
    }
    var editorBackground = theme.getColor(peekViewEditorBackground);
    if (editorBackground) {
        collector.addRule(".monaco-editor .reference-zone-widget .preview .monaco-editor .monaco-editor-background," +
            ".monaco-editor .reference-zone-widget .preview .monaco-editor .inputarea.ime-input {" +
            ("\tbackground-color: " + editorBackground + ";") +
            "}");
    }
    var editorGutterBackground = theme.getColor(peekViewEditorGutterBackground);
    if (editorGutterBackground) {
        collector.addRule(".monaco-editor .reference-zone-widget .preview .monaco-editor .margin {" +
            ("\tbackground-color: " + editorGutterBackground + ";") +
            "}");
    }
});
