/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import * as vscode from 'vscode';
import { ThemeIcon } from 'vscode';
import {  LanguageClient } from 'vscode-languageclient/node';
import { NbLanguageClient } from './extension';
import { NodeChangedParams, NodeInfoNotification, NodeInfoRequest, GetResourceParams, NodeChangeType, NodeChangesParams } from './protocol';

const doLog : boolean = false;
const EmptyIcon = "EMPTY_ICON";

/**
 * Listener that can watch for node structure or property changes.
 */
export interface TreeNodeListener {
  /**
   * Node has been destroyed. No more events will be delivered.
   * @param n the node
   */
  nodeDestroyed?(n : Visualizer) : void;

  /**
   * Node itself (description, icon, ...) has been changed.
   * @param n the node
   */
  nodeChanged?(n : Visualizer) : void;

  /**
   * Node's children changed.
   * @param n the node
   */
  nodeChildrenChanged?(n : Visualizer) : void;

  /**
   * Informs that some properties of the node changed. If list of properties is undefined, then
   * not only an unspecified property could change, but also the set of properties could be changed as well.
   * @param n the node
   * @param properties list of changed properties or undefined.
   */
  nodePropertiesChanged?(n : Visualizer, properties?: String[]) : void;
}

/**
 * Cached image information.
 */
class CachedImage {
  constructor(
    /**
     * Base URI of the image, if available.
     */
    public baseUri? : vscode.Uri,

    /**
     * Icon URI as sent by the LSP server. Images translated to ThemeIcons have this field undefined.
     */
    public iconUri? : vscode.Uri,

    /**
     * Local resource or theme icon.
     */
    public icon? : string | ThemeIcon,

    /**
     * Additional matched values
     */
    public values? : string[],
  ) {}
}

class ViewInfo {
  constructor(
    readonly treeView : vscode.TreeView<Visualizer>,
    readonly visProvider : VisualizerProvider)
    {}
}

export class TreeViewService extends vscode.Disposable {  
  
  private handler : vscode.Disposable | undefined;
  private client : NbLanguageClient;
  private trees : Map<string, ViewInfo> = new Map();
  private images : Map<number | vscode.Uri, CachedImage> = new Map();
  private providers : Map<number, VisualizerProvider> = new Map();
  log : vscode.OutputChannel;
  private entries : ImageEntry[] = [];

  constructor (log : vscode.OutputChannel, c : NbLanguageClient, dd : vscode.Disposable[]) {
    super(() => { 
      this.disposeAllViews(); 
      for (const d of dd) {
        d?.dispose();
      }
    });
    this.log = log;
    this.client = c;

    this.refreshImages();
    dd.push(vscode.extensions.onDidChange(() => this.refreshImages()));
  }

  getClient() : NbLanguageClient {
    return this.client;
  }

  private disposeAllViews() : void {
    for (let tree of this.trees.values()) {
      tree.visProvider.dispose();
      tree.treeView.dispose();
    }
    this.trees.clear();
    this.providers.clear();
    this.handler?.dispose();
  }

  public async createView(id : string, title? : string, options? : 
      Partial<vscode.TreeViewOptions<any> & { 
          providerInitializer : (provider : CustomizableTreeDataProvider<Visualizer>) => void }
      >) : Promise<vscode.TreeView<Visualizer> | undefined> {
    if (!this.client.isRunning()) {
      return undefined;
    }
    let tv : ViewInfo | undefined  = this.trees.get(id);
    if (tv) {
      return tv.treeView;
    }
    const res = await createViewProvider(this.client, id);
    this.providers.set(res.getRoot().data.id, res);
    options?.providerInitializer?.(res)
    let opts : vscode.TreeViewOptions<Visualizer> = {
      treeDataProvider : res,
      canSelectMany: true,
      showCollapseAll: true,
    }
    
    if (options?.canSelectMany !== undefined) {
      opts.canSelectMany = options.canSelectMany;
    }
    if (options?.showCollapseAll !== undefined) {
      opts.showCollapseAll = options.showCollapseAll;
    }
    let view = vscode.window.createTreeView(id, opts);
    this.trees.set(id, new ViewInfo(view, res));
    // this will replace the handler over and over, but never mind
    this.handler = this.client.onNotification(NodeInfoNotification.type, params => this.nodeChanged(params));
    return view;
  }

  private listeners: Map<string, {types : NodeChangeType[], listener : TreeNodeListener}[]> = new Map();

  private removeListenerRegistration(key : string, data : {types : NodeChangeType[], listener : TreeNodeListener}) : void {
    let a = this.listeners.get(key);
    if (!a) {
      return;
    }
    let index = a?.findIndex((x) => x === data);
    if (index !== undefined) {
      a?.splice(index, 1);
      if (!a?.length) {
        this.listeners.delete(key);
      }
    }
}

  public addNodeChangeListener(node : Visualizer, listener : TreeNodeListener, ...types : NodeChangeType[]) : vscode.Disposable {
    if (!this.client.isRunning()) {
      return new vscode.Disposable(() => {});
    }
    const listenerKey = node.rootId  + ':' + (node.id || '');
    let a = this.listeners.get(listenerKey);
    if (a === undefined) {
      a = [];
      this.listeners.set(listenerKey, a);
    }
    const data = { types, listener };
    a.push(data);
    
    let success = false;
    const r = this.client.sendRequest(NodeInfoRequest.changes, { rootId : node.rootId, nodeId: Number(node.id), types });
    r.catch(() => {
      // remove the listener registration
      this.removeListenerRegistration(listenerKey, data);
    });

    return new vscode.Disposable(() => {
      this.removeListenerRegistration(listenerKey, data);
    });
  }

  private nodeChanged(params : NodeChangedParams) : void {
    let p : VisualizerProvider | undefined = this.providers.get(params.rootId);
    if (!p) {
      return;
    }
    p.refresh(params);
    const key = params.rootId + ':' + (params.nodeId || '');
    const list = this.listeners.get(key);
    if (!list || !params.nodeId) {
      return;
    }
    const v = p.item(params.nodeId);
    if (!v) {
      return;
    }
    for (let { types, listener } of list) {
      if (!params.types) {
        // unspecified change
        listener.nodeChanged?.(v);
        continue;
      }
      const filtered = params.types.filter((t) => !types || types.indexOf(t) != -1);
      if (filtered.includes(NodeChangeType.CHILDEN)) {
        listener.nodeChildrenChanged?.(v);
      }
      if (filtered.includes(NodeChangeType.SELF)) {
        listener.nodeChanged?.(v);
      }
      if (filtered.includes(NodeChangeType.DESTROY)) {
        listener.nodeDestroyed?.(v);
      }
      if (filtered.includes(NodeChangeType.PROPERTY)) {
        listener.nodePropertiesChanged?.(v, params.properties);
      }
    }
  }

  /**
   * Requests an image data from the LSP server. 
   * @param nodeData 
   * @returns icon specification or undefined
   */
   async fetchImageUri(nodeData : NodeInfoRequest.Data) : Promise<vscode.Uri | string | ThemeIcon | undefined> {
    let res : vscode.Uri | string | ThemeIcon | undefined = this.imageUri(nodeData);

    if (!this.client.isRunning()) {
      return undefined;
    }
    if (res) {
      return res;
    }
    if (!nodeData?.iconDescriptor) {
      return undefined;
    }
    let ci : CachedImage | undefined;
    ci = this.images.get(nodeData.iconDescriptor.baseUri);
    if (ci != null) {
      return ci?.iconUri;
    }
    const p : GetResourceParams = {
      acceptEncoding: [ 'base64' ],
      uri : nodeData.iconDescriptor.baseUri
    };
    let iconData = await this.client.sendRequest(NodeInfoRequest.getresource, p);
    if (!iconData?.content) {
      return undefined;
    }
    let iconString = `data: ${iconData.contentType || 'image/png'};${iconData.encoding || 'base64'},${iconData.content}`;
    ci = new CachedImage(nodeData.iconDescriptor.baseUri, vscode.Uri.parse(iconString), undefined);
    this.images.set(nodeData.iconDescriptor.baseUri, ci);
    return ci.iconUri;
  }

  imageUri(nodeData : NodeInfoRequest.Data) : vscode.Uri | string | ThemeIcon | undefined {
    if (nodeData.id < 0) {
      return undefined;
    }

    let ci : CachedImage | undefined;
    if (nodeData.iconDescriptor?.baseUri) {
      const r = this.findProductIcon(nodeData.iconDescriptor.baseUri, nodeData.name, nodeData.contextValue);
      // override the icon with local.
      if (r) {
        if (r === EmptyIcon) {
          ci = new CachedImage(nodeData.iconDescriptor.baseUri, undefined, undefined, [ nodeData.name, nodeData.contextValue ]);
        }
        ci = new CachedImage(nodeData.iconDescriptor.baseUri, undefined, r, [ nodeData.name, nodeData.contextValue ]);
        this.images.set(nodeData.iconIndex, ci);
      }
    }
    if (!ci) {
      // hardcode visual vscode's File icons for regular files:
      if (nodeData.resourceUri && nodeData.contextValue.includes('is:file')) {
        const uri : vscode.Uri | undefined  = nodeData.iconUri ? vscode.Uri.parse(nodeData.iconUri) : undefined;
        // do not cache
        return ThemeIcon.File;
      }
    }
    return ci?.icon ? ci.icon : ci?.iconUri;
  }

  public setTranslations(entries : ImageEntry[]) {
    this.entries = entries;
  }

  public findProductIcon(res : vscode.Uri, ...values: string[]) : string | ThemeIcon | undefined {
    const s : string = res.toString();
    outer: for (let e of this.entries) {
      if (e.uriRegexp.test(s)) {
        if (e.valueRegexps) {
          let s : string = " " + values.join(" ") + " ";
          for (let vr of e.valueRegexps) {
            if (!vr.test(s)) {
              continue outer;
            }
          }
        }
        if (e.codeicon === '*file') {
          return ThemeIcon.File;
        } else if (e.codeicon == '*folder') {
          return ThemeIcon.Folder;
        } else if (e.codeicon == '') {
          return EmptyIcon;
        } else if (e.iconPath) {
          return e.iconPath;
        }
        let resultIcon;
        if (e.color) {
          resultIcon = new ThemeIcon(e.codeicon, new vscode.ThemeColor(e.color));
        } else {
          resultIcon = new ThemeIcon(e.codeicon);
        }
        
        return resultIcon;
      }
    }
    return undefined;
  }

  public refreshImages() {
    let newEntries : ImageEntry[] = [];
    for (const ext of vscode.extensions.all) {
      const iconMapping = ext.packageJSON?.contributes && ext.packageJSON?.contributes['netbeans.iconMapping'];
      if (Array.isArray(iconMapping)) {
        for (const m of iconMapping) {
          const reString = m?.uriExpression;
          if (reString) {
            try {
              let re : RegExp = new RegExp(reString);
              let vals = [];
              if (m?.valueMatch) {
                for (const vm of m.valueMatch) {
                  const re = new RegExp(vm);
                  vals.push(re);
                }
              }
              newEntries.push(new ImageEntry(re, m?.codeicon, m?.iconPath, vals, m?.color));
            } catch (e) {
              console.log("Invalid icon mapping in extension %s: %s -> %s", ext.id, reString, m?.codicon);
            }
          }
        }
      }
    }
    this.setTranslations(newEntries);
  }

  public async findPath(tree : vscode.TreeView<Visualizer>, selectData : any) : Promise<Visualizer | undefined> {
    let selected : ViewInfo | undefined;

    for (let vinfo of this.trees.values()) {
      if (vinfo.treeView === tree) {
        selected = vinfo;
      }
    }
    if (!selected) {
      return undefined;
    }

    return selected.visProvider.findTreeItem(selectData);
  }
}

export interface TreeItemDecorator<T> extends vscode.Disposable {
  decorateTreeItem(element: T, item : vscode.TreeItem): vscode.TreeItem | Thenable<vscode.TreeItem>;
  decorateChildren(element: T, children: Visualizer[]): Visualizer[] | Thenable<Visualizer[]>;
}

export interface CustomizableTreeDataProvider<T> extends vscode.TreeDataProvider<T> {
  fireItemChange(item? : T) : void;
  addItemDecorator(deco : TreeItemDecorator<T>) : vscode.Disposable;
  getRoot() : T;
}

class VisualizerProvider extends vscode.Disposable implements CustomizableTreeDataProvider<Visualizer> {
  private root: Visualizer;
  private treeData : Map<number, Visualizer> = new Map();
  private decorators : TreeItemDecorator<Visualizer>[] = [];
  
  constructor(
    private client: LanguageClient,
    private ts : TreeViewService,
    private log : vscode.OutputChannel,
    readonly id : string,
    rootData : NodeInfoRequest.Data,
    uri : vscode.Uri | string | ThemeIcon | undefined
  ) {
    super(() => this.disconnect());
    this.root = new Visualizer(rootData.id, rootData.id, rootData, uri);
    this.treeData.set(rootData.id, this.root);
  }

  private _onDidChangeTreeData: vscode.EventEmitter<Visualizer | undefined | null | void> = new vscode.EventEmitter<Visualizer | undefined | null | void>();
  readonly onDidChangeTreeData: vscode.Event<Visualizer | undefined | null | void> = this._onDidChangeTreeData.event;

  private disconnect() : void {
    // nothing at the moment.
    for (let deco of this.decorators) {
      deco.dispose();
    }
  }

  item(id : number) : Visualizer | undefined {
    return this.treeData.get(id);
  }

  fireItemChange(item : Visualizer | undefined) : void {
    if (doLog) {
      this.log.appendLine(`Firing change on ${item?.idstring()}`);
    }
    if (!item || item == this.root) {
      this._onDidChangeTreeData.fire();
    } else {
      this._onDidChangeTreeData.fire(item);
    }
  }

  addItemDecorator(decoInstance : TreeItemDecorator<Visualizer>) : vscode.Disposable {
    this.decorators.push(decoInstance);
    const self = this;
    return new vscode.Disposable(() => {
      const idx = this.decorators.indexOf(decoInstance);
      if (idx > 0) {
        this.decorators.splice(idx, 1);
        decoInstance.dispose();
      }
    });
  }

  refresh(params : NodeChangedParams): void {
      if (this.root.data.id === params.rootId) {
        let v : Visualizer | undefined;
        if (this. root.data.id == params.nodeId || !params.nodeId) {
          v = this.root;
        } else {
          v = this.treeData.get(params.nodeId);
        }
        if (v) {
          if (this.delayedFire.has(v)) {
            if (doLog) {
              this.log.appendLine(`Delaying change on ${v.idstring()}`);
            }
            v.pendingChange = true;
          } else {
            this.fireItemChange(v);
          }
        }
      }
  }

  async findTreeItem(toSelect : any) : Promise<Visualizer | undefined> {
    if (!this.client.isRunning()) {
      return;
    }
    let path : number[] = await this.client.sendRequest(NodeInfoRequest.findparams, { 
      selectData : toSelect,
      rootNodeId : Number(this.root.id)
    });
    if (!path) {
      return;
    }
    let current : Visualizer = this.root;
    if (path.length > 1 && path[0] == Number(this.root.id)) {
      path.shift();
    }
    
    for (let nodeId of path) {
      let children : Visualizer[];
      if (current.children) {
        children = Array.from(current.children.values());
      } else {
        children = await this.getChildren(current);
      }
      if (!children) {
        return undefined;
      }
      let selected : Visualizer | null = null;
      for (let c of children) {
        if (c.id == String(nodeId)) {
          selected = c;
          break;
        }
      }
      if (!selected) {
        return undefined;
      }
      current = selected;
    }
    return current;
  }

  getRoot() : Visualizer {
    return this.root.copy();
  }

  getParent(element : Visualizer) : Visualizer | null | Thenable<Visualizer | null> {
    // rely on that children was called first
    return element.parent;
  }

  getTreeItem(element: Visualizer): vscode.TreeItem | Thenable<vscode.TreeItem> {
    const n : number = Number(element.id);
    const self = this;
    if (doLog) {
      this.log.appendLine(`Doing getTreeItem on ${element.idstring()}`);
    }

    return this.wrap(async (arr) => {
      const pn : number = Number(element.parent?.id) || -1;
      let fetched = await this.queryVisualizer(element, arr, () => this.fetchItem(pn, n));
      let origin : vscode.TreeItem;
      if (fetched) {
        element.update(fetched);
        origin = await self.getTreeItem2(fetched);
      } else {
        // fire a change, this was unexpected
        const pn : number = Number(element.parent?.id) || -1;
        let pv = this.treeData.get(pn);
        if (pv) {
          this.fireItemChange(pv);
        }
        origin = element;
      }
      let ti : vscode.TreeItem = new vscode.TreeItem(origin.label || "", origin.collapsibleState);

      // See #4113 -- vscode broke icons display, if resourceUri is defined in TreeItem. We're OK with files,
      // but folders can have a semantic icon, so let hide resourceUri from vscode for folders.
      ti.command = origin.command;
      ti.contextValue = origin.contextValue;
      ti.description = origin.description;
      ti.iconPath = origin.iconPath;
      ti.id = origin.id;
      ti.label = origin.label;
      ti.tooltip = origin.tooltip;
      ti.accessibilityInformation = origin.accessibilityInformation;

      if (origin.resourceUri) {
        if (!origin.resourceUri.toString().endsWith("/")) {
          ti.resourceUri = origin.resourceUri;
        }
      }
      return ti;
    });
  }

  /**
   * Wraps code that queries individual Visualizers so that blocked changes are fired after
   * the code terminated.
   * 
   * Usage:
   * wrap(() => { ... code ... ; queryVisualizer(vis, () => { ... })});
   * @param fn the code to execute
   * @returns value of the code function
   */
  async wrap<X>(fn : (pending : Visualizer[]) => Thenable<X>) : Promise<X> {
    let arr : Visualizer[] = [];
    try {
      return await fn(arr);
    } finally {
      this.releaseVisualizersAndFire(arr);
    }
  }

  /**
   * Just creates a string list from visualizer IDs. Diagnostics only.
   */
  private visualizerList(arr : Visualizer[]) : string {
    let s = "";
    for (let v of arr) {
      s += v.idstring() + " ";
    }
    return s;
  }

  /**
   * Do not use directly, use wrap(). Fires delayed events for visualizers that have no pending queries.
   */
  private releaseVisualizersAndFire(list : Visualizer[] | undefined) {
    if (!list) {
      list = Array.from(this.delayedFire);
    }
    if (doLog) {
      this.log.appendLine(`Done with ${this.visualizerList(list)}`);
    }
    // v can be in list several times, each push increased its counter, so we need to decrease it.
    for (let v of list) {
      if (this.treeData?.get(Number(v.id || -1)) === v) {
        if (--v.pendingQueries) {
          if (doLog) {
            this.log.appendLine(`${v.idstring()} has pending ${v.pendingQueries} queries`);
          }
          continue;
        }
        if (v.pendingChange) {
          if (doLog) {
            this.log.appendLine(`Fire delayed change on ${v.idstring()}`);
          }
          this.fireItemChange(v);
          v.pendingChange = false;
        }
      }
      this.delayedFire.delete(v);
    }
    if (doLog) {
      this.log.appendLine("Pending queue: " + this.visualizerList(Array.from(this.delayedFire)));
      this.log.appendLine("---------------");
    }
  }

  /**
   * Should wrap calls to NBLS for individual visualizers (info, children). Puts visualizer on the delayed fire list.
   * Must be itself wrapped in wrap() -- wrap(... queryVisualizer()).
   * @param element visualizer to be queried, possibly undefined (new item is expected)
   * @param fn code to execute
   * @returns code's result
   */
  async queryVisualizer<X>(element : Visualizer | undefined, pending : Visualizer[], fn : () => Promise<X>) : Promise<X> {
    if (!element) {
      return fn();
    }
    this.delayedFire.add(element);
    pending.push(element);
    element.pendingQueries++;
    if (doLog) {
      this.log.appendLine(`Delaying visualizer ${element.idstring()}, queries = ${element.pendingQueries}`)
    }
    return fn();
  }

  async getTreeItem2(element: Visualizer): Promise<vscode.TreeItem> {
    const n = Number(element.id);
    if (this.decorators.length == 0) {
     return element;
    }
    let list : TreeItemDecorator<Visualizer>[] = [...this.decorators];
    
    async function f(item : vscode.TreeItem) : Promise<vscode.TreeItem> {
      const deco = list.shift();
      if (!deco) {
       return item;
      }
      const decorated = deco.decorateTreeItem(element, item);
      if (decorated instanceof vscode.TreeItem) {
          return f(decorated);
      } else {
         return (decorated as Thenable<vscode.TreeItem>).then(f);
      }
    }
    return f(element.copy());
  }

  delayedFire : Set<Visualizer> = new Set<Visualizer>();

  async fetchItem(parent : number, n : number) : Promise<Visualizer | undefined> {
    if (!this.client.isRunning()) {
      return;
    }
    let d = await this.client.sendRequest(NodeInfoRequest.info, { nodeId : n });
    if (!d || d?.id < 0) {
      return undefined;
    }
    let iconUri = await this.ts.fetchImageUri(d);
    let v = new Visualizer(this.root.data.id, n, d, iconUri);
    if (d.command) {
      // PENDING: provide an API to register command (+ parameters) -> command translators.
      if (d.command === 'vscode.open') {
        v.command = { command : d.command, title: '', arguments: [v.resourceUri]};
      } else {
        v.command = { command : d.command, title: '', arguments: [v]};
      }
    }
    return v;
  }

  getChildren(e?: Visualizer): Thenable<Visualizer[]> {
    const self = this;

    if (doLog) {
      this.log.appendLine(`Doing getChildren on ${e?.idstring()}`);
    }

    let decos : TreeItemDecorator<Visualizer>[] = [...this.decorators];
    const parent = e || this.root;
    async function collectResults(list : Visualizer[], arr: any, element: Visualizer): Promise<Visualizer[]> {
      let res : Visualizer[] = [];
      let now : Visualizer[] | undefined;
      const pn : number = Number(element.id) || -1;
      for (let i = 0; i < arr.length; i++) {
        const old : Visualizer | undefined = self.treeData.get(arr[i]);
        let v : Visualizer | undefined = await self.queryVisualizer(old, list, () => self.fetchItem(pn, arr[i]));
        if (v) {
          res.push(v);
        }
      }

      if (decos.length > 0) {
        async function f(orig: Visualizer[]) : Promise<Visualizer[]> {
          const deco = decos.shift();
          if (!deco) {
            return orig;
          }
          // decorateChildren(element: T, item : Visualizer, children: Visualizer[]): Visualizer[] | Thenable<Visualizer[]>;
          const decorated = deco.decorateChildren(parent, orig);
          if (Array.isArray(decorated)) {
              return f(decorated);
          } else {
              return (decorated as Thenable<Visualizer[]>).then(f);
          }
        }

        res = await f(res);
      }

      now = element.updateChildren(res, self);
      for (let i = 0; i < now.length; i++) {
        const v = now[i];
        const n : number = Number(v.id || -1);
        self.treeData.set(n, v);
        v.parent = element;
      }
      return now || [];
    }

    return self.wrap((list) => self.queryVisualizer(e, list, () => {
        if (!this.client.isRunning()) {
          return Promise.resolve([]);
        }
        return this.client.sendRequest(NodeInfoRequest.children, { nodeId : parent.data.id}).then(async (arr) => {
          return collectResults(list, arr, parent);
        });
      }
    ));
  }

  removeVisualizers(vis : number[]) {
    let ch : number[] = [];
    vis.forEach(a => {
      let v : Visualizer | undefined = this.treeData.get(a);
      if (v && v.children) {
        ch.push(...v.children.keys());
        this.treeData.delete(a);
      }
    });
    // cascade
    if (ch.length > 0) {
      this.removeVisualizers(ch);
    }
  }
}

let visualizerSerial = 1;

export class Visualizer extends vscode.TreeItem {
  
  visId : number;
  pendingQueries : number = 0;
  pendingChange : boolean = false;

  constructor(
    public rootId : number,
    explicitId : number,
    public data : NodeInfoRequest.Data,
    public image : vscode.Uri | string | ThemeIcon | undefined
  ) {
    super(data.id < 0 ? "< obsolete >" : data.label, data.collapsibleState);
    this.visId = visualizerSerial++;
    this.id = "" + explicitId;
    this.label = data.label;
    this.description = data.description;
    this.tooltip = data.tooltip;
    this.collapsibleState = data.collapsibleState;
    this.iconPath = image;
    if (data.resourceUri) {
        this.resourceUri = vscode.Uri.parse(data.resourceUri);
    }
    this.contextValue = data.contextValue;
  }

  copy() : Visualizer {
    let v : Visualizer = new Visualizer(this.rootId, Number(this.id), this.data, this.image);
    v.id = this.id;
    v.label = this.label;
    v.description = this.description;
    v.tooltip = this.tooltip;
    v.iconPath = this.iconPath;
    v.resourceUri = this.resourceUri;
    v.contextValue = this.contextValue;
    return v;
  }

  parent: Visualizer | null = null;
  children: Map<number, Visualizer> | null = null;

  idstring() : string {
    return `[${this.id} : ${this.visId} - "${this.label}"]`;
  }

  update(other : Visualizer) : Visualizer {
    this.label = other.label;
    this.description = other.description;
    this.tooltip = other.tooltip;
    this.collapsibleState = other.collapsibleState;
    this.iconPath = other.iconPath;
    this.resourceUri = other.resourceUri;
    this.contextValue = other.contextValue;
    this.data = other.data;
    this.image = other.image;
    this.collapsibleState = other.collapsibleState;
    this.command = other.command;
    return this;
  }

  updateChildren(newChildren : Visualizer[], provider : VisualizerProvider) : Visualizer[] {
    let toRemove : number[] = [];
    let ch : Map<number, Visualizer> = new Map();

    for (let i = 0; i < newChildren.length; i++) {
      let c = newChildren[i];
      const n : number = Number(c.id || -1);
      const v : Visualizer | undefined = this.children?.get(n);
      if (v) {
        v.update(c);
        newChildren[i] = c = v;
      }
      ch.set(n, c);
    }

    if (this.children) {
      for (let k of this.children.keys()) {
        if (!ch.get(k)) {
          toRemove.push(k);
        }
      }
    }
    this.children = ch;
    if (toRemove.length) {
      provider.removeVisualizers(toRemove);
    }
    return newChildren;
  }
}

class ImageEntry {
  constructor(
    readonly uriRegexp : RegExp,
    readonly codeicon : string,
    readonly iconPath? : string,
    readonly valueRegexps? : RegExp[],
    readonly color?: string
    ) {}
}
class ImageTranslator {
  private entries : ImageEntry[] = [];

  public setTranslations(entries : ImageEntry[]) {
    this.entries = entries;
  }

  public findProductIcon(res : string) : string | undefined {
    for (let e of this.entries) {
      if (e.uriRegexp.exec(res)) {
        return e.codeicon;
      }
    }
    return undefined;
  }
}

export async function createViewProvider(c : NbLanguageClient, id : string) : Promise<VisualizerProvider> {
  const ts = c.findTreeViewService();
  const client = ts.getClient();
  const res = client.sendRequest(NodeInfoRequest.explorermanager, { explorerId: id }).then(async node => {
    if (!node) {
      throw "Unsupported view: " + id;
    }
    return new VisualizerProvider(client, ts, ts.log, id, node, await ts.fetchImageUri(node));
  });
  if (!res) {
    throw "Unsupported view: " + id;
  }
  return res;
}
/**
 * Creates a view of the specified type or returns an existing one. The View has to be registered in package.json in
 * some workspace position. Waits until the view service initializes.
 * 
 * @param id view ID, consistent with package.json registration
 * @param viewTitle title for the new view, optional.
 * @returns promise of the tree view instance.
 */
export async function createTreeView<T>(c: NbLanguageClient, viewId: string, viewTitle? : string, options? : Partial<vscode.TreeViewOptions<any>>) : Promise<vscode.TreeView<Visualizer>|undefined> {
  let ts = c.findTreeViewService();
  return ts.createView(viewId, viewTitle, options);
}

/**
 * Registers the treeview service with the language server.
 */
export function createTreeViewService(log : vscode.OutputChannel, c : NbLanguageClient): TreeViewService {
    const d = vscode.commands.registerCommand("foundProjects.deleteEntry", async function (this: any, args: any) {
        let v = args as Visualizer;
        let ok = await c.sendRequest(NodeInfoRequest.destroy, { nodeId : v.data.id });
        if (!ok) {
            vscode.window.showErrorMessage('Cannot delete node ' + v.label);
        }
    });
    const ts : TreeViewService = new TreeViewService(log, c, [ d ]);
    return ts;
}

