// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library heap_map_element;

import 'dart:async';
import 'dart:html';
import 'dart:math';
import 'package:observatory/models.dart' as M;
import 'package:observatory/service.dart' as S;
import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory/src/elements/helpers/nav_bar.dart';
import 'package:observatory/src/elements/helpers/nav_menu.dart';
import 'package:observatory/src/elements/helpers/tag.dart';
import 'package:observatory/src/elements/helpers/uris.dart';
import 'package:observatory/src/elements/nav/isolate_menu.dart';
import 'package:observatory/src/elements/nav/notify.dart';
import 'package:observatory/src/elements/nav/refresh.dart';
import 'package:observatory/src/elements/nav/top_menu.dart';
import 'package:observatory/src/elements/nav/vm_menu.dart';

class HeapMapElement extends HtmlElement implements Renderable {
  static const tag = const Tag<HeapMapElement>('heap-map', dependencies: const [
    NavTopMenuElement.tag,
    NavVMMenuElement.tag,
    NavIsolateMenuElement.tag,
    NavRefreshElement.tag,
    NavNotifyElement.tag,
  ]);

  RenderingScheduler<HeapMapElement> _r;

  Stream<RenderedEvent<HeapMapElement>> get onRendered => _r.onRendered;

  M.VM _vm;
  M.IsolateRef _isolate;
  M.EventRepository _events;
  M.NotificationRepository _notifications;
  M.VMRef get vm => _vm;
  M.IsolateRef get isolate => _isolate;
  M.NotificationRepository get notifications => _notifications;

  factory HeapMapElement(M.VM vm, M.IsolateRef isolate,
      M.EventRepository events, M.NotificationRepository notifications,
      {RenderingQueue queue}) {
    assert(vm != null);
    assert(isolate != null);
    assert(events != null);
    assert(notifications != null);
    HeapMapElement e = document.createElement(tag.name);
    e._r = new RenderingScheduler<HeapMapElement>(e, queue: queue);
    e._vm = vm;
    e._isolate = isolate;
    e._events = events;
    e._notifications = notifications;
    return e;
  }

  HeapMapElement.created() : super.created();

  @override
  attached() {
    super.attached();
    _r.enable();
    _refresh();
  }

  @override
  detached() {
    super.detached();
    _r.disable(notify: true);
    children = <Element>[];
  }

  CanvasElement _canvas;
  var _fragmentationData;
  double _pageHeight;
  final _classIdToColor = {};
  final _colorToClassId = {};
  final _classIdToName = {};

  static final _freeColor = [255, 255, 255, 255];
  static final _pageSeparationColor = [0, 0, 0, 255];
  static const _PAGE_SEPARATION_HEIGHT = 4;
  // Many browsers will not display a very tall canvas.
  // TODO(koda): Improve interface for huge heaps.
  static const _MAX_CANVAS_HEIGHT = 6000;

  String _status;
  S.ServiceMap _fragmentation;

  void render() {
    if (_canvas == null) {
      _canvas = new CanvasElement()
        ..width = 1
        ..height = 1
        ..onMouseMove.listen(_handleMouseMove)
        ..onMouseDown.listen(_handleClick);
    }

    // Set hover text to describe the object under the cursor.
    _canvas.title = _status;

    children = <Element>[
      navBar(<Element>[
        new NavTopMenuElement(queue: _r.queue),
        new NavVMMenuElement(_vm, _events, queue: _r.queue),
        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
        navMenu('heap map'),
        new NavRefreshElement(label: 'Mark-Compact', queue: _r.queue)
          ..onRefresh.listen((_) => _refresh(gc: "mark-compact")),
        new NavRefreshElement(label: 'Mark-Sweep', queue: _r.queue)
          ..onRefresh.listen((_) => _refresh(gc: "mark-sweep")),
        new NavRefreshElement(label: 'Scavenge', queue: _r.queue)
          ..onRefresh.listen((_) => _refresh(gc: "scavenge")),
        new NavRefreshElement(queue: _r.queue)
          ..onRefresh.listen((_) => _refresh()),
        new NavNotifyElement(_notifications, queue: _r.queue)
      ]),
      new DivElement()
        ..classes = ['content-centered-big']
        ..children = <Element>[
          new HeadingElement.h2()..text = _status,
          new HRElement(),
        ],
      new DivElement()
        ..classes = ['flex-row']
        ..children = <Element>[_canvas]
    ];
  }

  // Encode color as single integer, to enable using it as a map key.
  int _packColor(Iterable<int> color) {
    int packed = 0;
    for (var component in color) {
      packed = packed * 256 + component;
    }
    return packed;
  }

  void _addClass(int classId, String name, Iterable<int> color) {
    _classIdToName[classId] = name.split('@')[0];
    _classIdToColor[classId] = color;
    _colorToClassId[_packColor(color)] = classId;
  }

  void _updateClassList(classList, int freeClassId) {
    for (var member in classList['classes']) {
      if (member is! S.Class) {
        // TODO(turnidge): The printing for some of these non-class
        // members is broken.  Fix this:
        //
        // Logger.root.info('$member');
        print('Ignoring non-class in class list');
        continue;
      }
      var classId = int.parse(member.id.split('/').last);
      var color = _classIdToRGBA(classId);
      _addClass(classId, member.name, color);
    }
    _addClass(freeClassId, 'Free', _freeColor);
    _addClass(0, '', _pageSeparationColor);
  }

  Iterable<int> _classIdToRGBA(int classId) {
    // TODO(koda): Pick random hue, but fixed saturation and value.
    var rng = new Random(classId);
    return [rng.nextInt(128), rng.nextInt(128), rng.nextInt(128), 255];
  }

  String _classNameAt(Point<num> point) {
    var color = new PixelReference(_fragmentationData, point).color;
    return _classIdToName[_colorToClassId[_packColor(color)]];
  }

  ObjectInfo _objectAt(Point<num> point) {
    if (_fragmentation == null || _canvas == null) {
      return null;
    }
    var pagePixels = _pageHeight * _fragmentationData.width;
    var index = new PixelReference(_fragmentationData, point).index;
    var pageIndex = index ~/ pagePixels;
    num pageOffset = index % pagePixels;
    var pages = _fragmentation['pages'];
    if (pageIndex < 0 || pageIndex >= pages.length) {
      return null;
    }
    // Scan the page to find start and size.
    var page = pages[pageIndex];
    var objects = page['objects'];
    var offset = 0;
    var size = 0;
    for (var i = 0; i < objects.length; i += 2) {
      size = objects[i];
      offset += size;
      if (offset > pageOffset) {
        pageOffset = offset - size;
        break;
      }
    }
    return new ObjectInfo(
        int.parse(page['objectStart']) +
            pageOffset * _fragmentation['unitSizeBytes'],
        size * _fragmentation['unitSizeBytes']);
  }

  void _handleMouseMove(MouseEvent event) {
    var info = _objectAt(event.offset);
    if (info == null) {
      _status = '';
      _r.dirty();
      return;
    }
    var addressString = '${info.size}B @ 0x${info.address.toRadixString(16)}';
    var className = _classNameAt(event.offset);
    _status = (className == '') ? '-' : '$className $addressString';
    _r.dirty();
  }

  void _handleClick(MouseEvent event) {
    final isolate = _isolate as S.Isolate;
    final address = _objectAt(event.offset).address.toRadixString(16);
    isolate.getObjectByAddress(address).then((result) {
      if (result.type != 'Sentinel') {
        new AnchorElement(href: Uris.inspect(_isolate, object: result)).click();
      }
    });
  }

  void _updateFragmentationData() {
    if (_fragmentation == null || _canvas == null) {
      return;
    }
    _updateClassList(
        _fragmentation['classList'], _fragmentation['freeClassId']);
    var pages = _fragmentation['pages'];
    var width = max(_canvas.parent.client.width, 1);
    _pageHeight = _PAGE_SEPARATION_HEIGHT +
        _fragmentation['pageSizeBytes'] ~/
            _fragmentation['unitSizeBytes'] ~/
            width;
    var height = min(_pageHeight * pages.length, _MAX_CANVAS_HEIGHT);
    _fragmentationData = _canvas.context2D.createImageData(width, height);
    _canvas.width = _fragmentationData.width;
    _canvas.height = _fragmentationData.height;
    _renderPages(0);
  }

  // Renders and draws asynchronously, one page at a time to avoid
  // blocking the UI.
  void _renderPages(int startPage) {
    var pages = _fragmentation['pages'];
    _status = 'Loaded $startPage of ${pages.length} pages';
    _r.dirty();
    var startY = (startPage * _pageHeight).round();
    var endY = startY + _pageHeight.round();
    if (startPage >= pages.length || endY > _fragmentationData.height) {
      return;
    }
    var pixel = new PixelReference(_fragmentationData, new Point(0, startY));
    var objects = pages[startPage]['objects'];
    for (var i = 0; i < objects.length; i += 2) {
      var count = objects[i];
      var classId = objects[i + 1];
      var color = _classIdToColor[classId];
      while (count-- > 0) {
        pixel.color = color;
        pixel = pixel.next();
      }
    }
    while (pixel.point.y < endY) {
      pixel.color = _pageSeparationColor;
      pixel = pixel.next();
    }
    _canvas.context2D.putImageData(
        _fragmentationData, 0, 0, 0, startY, _fragmentationData.width, endY);
    // Continue with the next page, asynchronously.
    new Future(() {
      _renderPages(startPage + 1);
    });
  }

  Future _refresh({String gc}) {
    final isolate = _isolate as S.Isolate;
    var params = {};
    if (gc != null) {
      params['gc'] = gc;
    }
    return isolate.invokeRpc('_getHeapMap', params).then((serviceObject) {
      S.ServiceMap response = serviceObject;
      assert(response['type'] == 'HeapMap');
      _fragmentation = response;
      _updateFragmentationData();
    });
  }
}

// A reference to a particular pixel of ImageData.
class PixelReference {
  final _data;
  var _dataIndex;
  static const NUM_COLOR_COMPONENTS = 4;

  PixelReference(ImageData data, Point<num> point)
      : _data = data,
        _dataIndex = (point.y * data.width + point.x) * NUM_COLOR_COMPONENTS;

  PixelReference._fromDataIndex(this._data, this._dataIndex);

  Point<num> get point => new Point(index % _data.width, index ~/ _data.width);

  void set color(Iterable<int> color) {
    _data.data.setRange(_dataIndex, _dataIndex + NUM_COLOR_COMPONENTS, color);
  }

  Iterable<int> get color =>
      _data.data.getRange(_dataIndex, _dataIndex + NUM_COLOR_COMPONENTS);

  // Returns the next pixel in row-major order.
  PixelReference next() => new PixelReference._fromDataIndex(
      _data, _dataIndex + NUM_COLOR_COMPONENTS);

  // The row-major index of this pixel.
  int get index => _dataIndex ~/ NUM_COLOR_COMPONENTS;
}

class ObjectInfo {
  final address;
  final size;
  ObjectInfo(this.address, this.size);
}
