// Copyright (c) 2015, 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.

part of dart._vmservice;

class Asset {
  final String name;
  final Uint8List data;

  Asset(this.name, this.data);

  String get mimeType {
    var extensionStart = name.lastIndexOf('.');
    var extension = name.substring(extensionStart+1);
    switch (extension) {
      case 'html':
        return 'text/html; charset=UTF-8';
      case 'dart':
        return 'application/dart; charset=UTF-8';
      case 'js':
        return 'application/javascript; charset=UTF-8';
      case 'css':
        return 'text/css; charset=UTF-8';
      case 'gif':
        return 'image/gif';
      case 'png':
        return 'image/png';
      case 'jpg':
        return 'image/jpeg';
      case 'jpeg':
        return 'image/jpeg';
      case 'svg':
        return 'image/svg+xml';
      default:
        return 'text/plain';
    }
  }

  /// Call to request assets from the embedder.
  static HashMap<String, Asset> request() {
    HashMap<String, Asset> assets = new HashMap<String, Asset>();
    Uint8List tarBytes = _requestAssets();
    if (tarBytes == null) {
      return assets;
    }
    _TarArchive archive = new _TarArchive(tarBytes);
    while (archive.hasNext()) {
      Asset asset = archive.next();
      if (asset == null) {
        // Skip over special files.
        continue;
      }
      assets[asset.name] = asset;
    }
    return assets;
  }

  String toString() => '$name ($mimeType)';
}

HashMap<String, Asset> _assets;
HashMap<String, Asset> get assets {
  if (_assets == null) {
    try {
      _assets = Asset.request();
    } catch (e) {
      print('Could not load Observatory assets: $e');
    }
  }
  return _assets;
}

class _ByteStream {
  final Uint8List bytes;
  final int offset;
  int get length => bytes.length - offset;
  int _cursor = 0;

  _ByteStream(this.bytes, [this.offset = 0]);

  void reset() {
    _cursor = 0;
  }

  int peekByte([int index = 0]) => bytes[offset + _cursor + index];

  int readByte() {
    int r = peekByte();
    _advance(1);
    return r;
  }

  void skip(int bytes) => _advance(bytes);

  void seekToNextBlock(int blockSize) {
    int remainder = blockSize - (_cursor % blockSize);
    _advance(remainder);
  }

  void _advance(int bytes) {
    _cursor += bytes;
    if (_cursor > length) {
      _cursor = length;
    }
  }

  int get remaining => length - _cursor;
  bool get hasMore => remaining > 0;
  int get cursor => _cursor;
  void set cursor(int cursor) {
    _cursor = cursor;
    if (_cursor > length) {
      _cursor = length;
    }
  }
}

class _TarArchive {
  static const List<int> tarMagic = const [ 0x75, 0x73, 0x74, 0x61, 0x72, 0 ];
  static const List<int> tarVersion = const [ 0x30, 0x30 ];
  static const int tarHeaderSize = 512;
  static const int tarHeaderFilenameSize = 100;
  static const int tarHeaderFilenameOffset = 0;
  static const int tarHeaderSizeSize = 12;
  static const int tarHeaderSizeOffset = 124;
  static const int tarHeaderTypeSize = 1;
  static const int tarHeaderTypeOffset = 156;
  static const int tarHeaderFileType = 0x30;

  static String _readCString(_ByteStream bs, int length) {
    StringBuffer sb = new StringBuffer();
    int count = 0;
    while (bs.hasMore && count < length) {
      if (bs.peekByte() == 0) {
        // Null character.
        break;
      }
      sb.writeCharCode(bs.readByte());
      count++;
    }
    return sb.toString();
  }

  static String _readFilename(_ByteStream bs) {
    String filename = _readCString(bs, tarHeaderFilenameSize);
    if (filename.startsWith('/')) {
      return filename;
    }
    return '/' + filename;
  }

  static Uint8List _readContents(_ByteStream bs, int size) {
    Uint8List result = new Uint8List(size);
    int i = 0;
    while (bs.hasMore && i < size) {
      result[i] = bs.readByte();
      i++;
    }
    bs.seekToNextBlock(tarHeaderSize);
    return result;
  }

  static void _skipContents(_ByteStream bs, int size) {
    bs.skip(size);
    bs.seekToNextBlock(tarHeaderSize);
  }

  static int _readSize(_ByteStream bs) {
    String octalSize = _readCString(bs, tarHeaderSizeSize);
    return int.parse(octalSize,
                     radix: 8,
                     onError: (_) => 0);
  }

  static int _readType(_ByteStream bs) {
    return bs.readByte();
  }

  static bool _endOfArchive(_ByteStream bs) {
    if (bs.remaining < (tarHeaderSize * 2)) {
      return true;
    }
    for (int i = 0; i < (tarHeaderSize * 2); i++) {
      if (bs.peekByte(i) != 0) {
        return false;
      }
    }
    return true;
  }

  final _ByteStream _bs;

  _TarArchive(Uint8List bytes)
      : _bs = new _ByteStream(bytes);

  bool hasNext() {
    return !_endOfArchive(_bs);
  }

  Asset next() {
    int startOfBlock = _bs.cursor;
    String filename = _readFilename(_bs);
    _bs.cursor = startOfBlock + tarHeaderSizeOffset;
    int size = _readSize(_bs);
    _bs.cursor = startOfBlock + tarHeaderTypeOffset;
    int type = _readType(_bs);
    _bs.seekToNextBlock(tarHeaderSize);
    if (type != tarHeaderFileType) {
      _skipContents(_bs, size);
      return null;
    }
    Uint8List bytes = _readContents(_bs, size);
    return new Asset(filename, bytes);
  }
}
