// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:typed_data';
import 'mojo:bindings' as bindings;
import 'mojo:core' as core;

import 'package:mojo/dart/testing/expect.dart';

class Bar extends bindings.Struct {
  static const int kStructSize = 16;
  static const bindings.StructDataHeader kDefaultStructInfo =
      const bindings.StructDataHeader(kStructSize, 4);

  static final int Type_VERTICAL = 1;
  static final int Type_HORIZONTAL = Type_VERTICAL + 1;
  static final int Type_BOTH = Type_HORIZONTAL + 1;
  static final int Type_INVALID = Type_BOTH + 1;
  int alpha;
  int beta;
  int gamma;
  int type;

  Bar() : super(kStructSize) {
    alpha = 0xff;
    type = Bar.Type_VERTICAL;
  }

  static Bar deserialize(bindings.Message message) {
    return decode(new bindings.Decoder(message));
  }

  static Bar decode(bindings.Decoder decoder0) {
    if (decoder0 == null) {
      return null;
    }
    Bar result = new Bar();
    var mainDataHeader = decoder0.decodeStructDataHeader();
    if (mainDataHeader.version > 0) {
      result.alpha = decoder0.decodeUint8(8);
    }
    if (mainDataHeader.version > 1) {
      result.beta = decoder0.decodeUint8(9);
    }
    if (mainDataHeader.version > 2) {
      result.gamma = decoder0.decodeUint8(10);
    }
    if (mainDataHeader.version > 3) {
      result.type = decoder0.decodeInt32(12);
    }
    return result;
  }

  void encode(bindings.Encoder encoder) {
    var encoder0 = encoder.getStructEncoderAtOffset(kDefaultStructInfo);
    encoder0.encodeUint8(alpha, 8);
    encoder0.encodeUint8(beta, 9);
    encoder0.encodeUint8(gamma, 10);
    encoder0.encodeInt32(type, 12);
  }
}


void testBar() {
  var bar = new Bar();
  bar.alpha = 1;
  bar.beta = 2;
  bar.gamma = 3;
  bar.type = 0x08070605;

  int name = 42;
  var header = new bindings.MessageHeader(name);
  var message = bar.serializeWithHeader(header);

  var expectedMemory = new Uint8List.fromList([
    16, 0, 0, 0,
     2, 0, 0, 0,
    42, 0, 0, 0,
     0, 0, 0, 0,

    16, 0, 0, 0,
     4, 0, 0, 0,

     1, 2, 3, 0,
     5, 6, 7, 8,
  ]);

  var actualMemory = message.buffer.buffer.asUint8List();
  Expect.listEquals(expectedMemory, actualMemory);

  var receivedMessage = new bindings.ServiceMessage.fromMessage(message);

  Expect.equals(receivedMessage.header.size, header.size);
  Expect.equals(receivedMessage.header.type, header.type);

  var bar2 = Bar.deserialize(receivedMessage.payload);

  Expect.equals(bar.alpha, bar2.alpha);
  Expect.equals(bar.beta, bar2.beta);
  Expect.equals(bar.gamma, bar2.gamma);
  Expect.equals(bar.type, bar2.type);
}


class Foo extends bindings.Struct {
  static const int kStructSize = 96;
  static const bindings.StructDataHeader kDefaultStructInfo =
      const bindings.StructDataHeader(kStructSize, 15);
  static final kFooby = "Fooby";
  int x = 0;
  int y = 0;
  bool a = true;
  bool b = false;
  bool c = false;
  core.MojoHandle source = null;
  Bar bar = null;
  List<int> data = null;
  List<Bar> extraBars = null;
  String name = Foo.kFooby;
  List<core.MojoHandle> inputStreams = null;
  List<core.MojoHandle> outputStreams = null;
  List<List<bool>> arrayOfArrayOfBools = null;
  List<List<List<String>>> multiArrayOfStrings = null;
  List<bool> arrayOfBools = null;

  Foo() : super(kStructSize);

  static Foo deserialize(bindings.Message message) {
    return decode(new bindings.Decoder(message));
  }

  static Foo decode(bindings.Decoder decoder0) {
    if (decoder0 == null) {
      return null;
    }
    Foo result = new Foo();
    var mainDataHeader = decoder0.decodeStructDataHeader();
    if (mainDataHeader.version > 0) {
      result.x = decoder0.decodeInt32(8);
    }
    if (mainDataHeader.version > 1) {
      result.y = decoder0.decodeInt32(12);
    }
    if (mainDataHeader.version > 2) {
      result.a = decoder0.decodeBool(16, 0);
    }
    if (mainDataHeader.version > 3) {
      result.b = decoder0.decodeBool(16, 1);
    }
    if (mainDataHeader.version > 4) {
      result.c = decoder0.decodeBool(16, 2);
    }
    if (mainDataHeader.version > 9) {
      result.source = decoder0.decodeHandle(20, true);
    }
    if (mainDataHeader.version > 5) {
      var decoder1 = decoder0.decodePointer(24, true);
      result.bar = Bar.decode(decoder1);
    }
    if (mainDataHeader.version > 6) {
      result.data = decoder0.decodeUint8Array(
          32, bindings.kArrayNullable, bindings.kUnspecifiedArrayLength);
    }
    if (mainDataHeader.version > 7) {
      var decoder1 = decoder0.decodePointer(40, true);
      if (decoder1 == null) {
        result.extraBars = null;
      } else {
        var si1 = decoder1.decodeDataHeaderForPointerArray(
            bindings.kUnspecifiedArrayLength);
        result.extraBars = new List<Bar>(si1.numElements);
        for (int i1 = 0; i1 < si1.numElements; ++i1) {
          var decoder2 = decoder1.decodePointer(
              bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1,
              false);
          result.extraBars[i1] = Bar.decode(decoder2);
        }
      }
    }
    if (mainDataHeader.version > 8) {
      result.name = decoder0.decodeString(48, false);
    }
    if (mainDataHeader.version > 10) {
      result.inputStreams = decoder0.decodeHandleArray(
          56, bindings.kArrayNullable, bindings.kUnspecifiedArrayLength);
    }
    if (mainDataHeader.version > 11) {
      result.outputStreams = decoder0.decodeHandleArray(
          64, bindings.kArrayNullable, bindings.kUnspecifiedArrayLength);
    }
    if (mainDataHeader.version > 12) {
      var decoder1 = decoder0.decodePointer(72, true);
      if (decoder1 == null) {
        result.arrayOfArrayOfBools = null;
      } else {
        var si1 = decoder1.decodeDataHeaderForPointerArray(
            bindings.kUnspecifiedArrayLength);
        result.arrayOfArrayOfBools = new List<List<bool>>(si1.numElements);
        for (int i1 = 0; i1 < si1.numElements; ++i1) {
          result.arrayOfArrayOfBools[i1] = decoder1.decodeBoolArray(
              bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1,
              bindings.kNothingNullable,
              bindings.kUnspecifiedArrayLength);
        }
      }
    }
    if (mainDataHeader.version > 13) {
      var decoder1 = decoder0.decodePointer(80, true);
      if (decoder1 == null) {
        result.multiArrayOfStrings = null;
      } else {
        var si1 = decoder1.decodeDataHeaderForPointerArray(
            bindings.kUnspecifiedArrayLength);
        result.multiArrayOfStrings =
            new List<List<List<String>>>(si1.numElements);
        for (int i1 = 0; i1 < si1.numElements; ++i1) {
          var decoder2 = decoder1.decodePointer(
              bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1,
              false);
          {
            var si2 = decoder2.decodeDataHeaderForPointerArray(
                bindings.kUnspecifiedArrayLength);
            result.multiArrayOfStrings[i1] =
                new List<List<String>>(si2.numElements);
            for (int i2 = 0; i2 < si2.numElements; ++i2) {
              var decoder3 = decoder2.decodePointer(
                  bindings.ArrayDataHeader.kHeaderSize +
                      bindings.kPointerSize * i2,
                  false);
              {
                var si3 = decoder3.decodeDataHeaderForPointerArray(
                    bindings.kUnspecifiedArrayLength);
                result.multiArrayOfStrings[i1][i2] =
                    new List<String>(si3.numElements);
                for (int i3 = 0; i3 < si3.numElements; ++i3) {
                  var length = bindings.ArrayDataHeader.kHeaderSize +
                               bindings.kPointerSize * i3;
                  result.multiArrayOfStrings[i1][i2][i3] =
                      decoder3.decodeString(length, false);
                }
              }
            }
          }
        }
      }
    }
    if (mainDataHeader.version > 14) {
      result.arrayOfBools = decoder0.decodeBoolArray(
          88, bindings.kArrayNullable, bindings.kUnspecifiedArrayLength);
    }
    return result;
  }

  void encode(bindings.Encoder encoder) {
    var encoder0 = encoder.getStructEncoderAtOffset(kDefaultStructInfo);
    encoder0.encodeInt32(x, 8);
    encoder0.encodeInt32(y, 12);
    encoder0.encodeBool(a, 16, 0);
    encoder0.encodeBool(b, 16, 1);
    encoder0.encodeBool(c, 16, 2);
    encoder0.encodeHandle(source, 20, true);
    encoder0.encodeStruct(bar, 24, true);
    encoder0.encodeUint8Array(
        data, 32, bindings.kArrayNullable, bindings.kUnspecifiedArrayLength);

    if (extraBars == null) {
      encoder0.encodeNullPointer(40, true);
    } else {
      var encoder1 = encoder0.encodePointerArray(
          extraBars.length, 40, bindings.kUnspecifiedArrayLength);
      for (int i0 = 0; i0 < extraBars.length; ++i0) {
        encoder1.encodeStruct(
            extraBars[i0],
            bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0,
            false);
      }
    }

    encoder0.encodeString(name, 48, false);
    encoder0.encodeHandleArray(inputStreams,
                               56,
                               bindings.kArrayNullable,
                               bindings.kUnspecifiedArrayLength);
    encoder0.encodeHandleArray(outputStreams,
                               64,
                               bindings.kArrayNullable,
                               bindings.kUnspecifiedArrayLength);

    if (arrayOfArrayOfBools == null) {
      encoder0.encodeNullPointer(72, true);
    } else {
      var encoder1 = encoder0.encodePointerArray(
          arrayOfArrayOfBools.length, 72, bindings.kUnspecifiedArrayLength);
      for (int i0 = 0; i0 < arrayOfArrayOfBools.length; ++i0) {
        encoder1.encodeBoolArray(
            arrayOfArrayOfBools[i0],
            bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0,
            bindings.kNothingNullable,
            bindings.kUnspecifiedArrayLength);
      }
    }

    if (multiArrayOfStrings == null) {
      encoder0.encodeNullPointer(80, true);
    } else {
      var encoder1 = encoder0.encodePointerArray(
          multiArrayOfStrings.length, 80, bindings.kUnspecifiedArrayLength);
      for (int i0 = 0; i0 < multiArrayOfStrings.length; ++i0) {
        if (multiArrayOfStrings[i0] == null) {
          encoder1.encodeNullPointer(
              bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0,
              false);
        } else {
          var encoder2 = encoder1.encodePointerArray(
              multiArrayOfStrings[i0].length,
              bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0,
              bindings.kUnspecifiedArrayLength);
          for (int i1 = 0; i1 < multiArrayOfStrings[i0].length; ++i1) {
            if (multiArrayOfStrings[i0][i1] == null) {
              encoder2.encodeNullPointer(
                  bindings.ArrayDataHeader.kHeaderSize +
                      bindings.kPointerSize * i1,
                  false);
            } else {
              var encoder3 = encoder2.encodePointerArray(
                  multiArrayOfStrings[i0][i1].length,
                  bindings.ArrayDataHeader.kHeaderSize +
                      bindings.kPointerSize * i1,
                  bindings.kUnspecifiedArrayLength);
              for (int i2 = 0; i2 < multiArrayOfStrings[i0][i1].length; ++i2) {
                var length = bindings.ArrayDataHeader.kHeaderSize +
                             bindings.kPointerSize * i2;
                encoder3.encodeString(
                    multiArrayOfStrings[i0][i1][i2],
                    length,
                    false);
              }
            }
          }
        }
      }
    }

    encoder0.encodeBoolArray(arrayOfBools,
                             88,
                             bindings.kArrayNullable,
                             bindings.kUnspecifiedArrayLength);
  }
}


void testFoo() {
  var foo = new Foo();
  foo.x = 0x212B4D5;
  foo.y = 0x16E93;
  foo.a = true;
  foo.b = false;
  foo.c = true;
  foo.bar = new Bar();
  foo.bar.alpha = 91;
  foo.bar.beta = 82;
  foo.bar.gamma = 73;
  foo.data = [
    4, 5, 6, 7, 8,
  ];
  foo.extraBars = [
    new Bar(), new Bar(), new Bar(),
  ];
  for (int i = 0; i < foo.extraBars.length; ++i) {
    foo.extraBars[i].alpha = 1 * i;
    foo.extraBars[i].beta = 2 * i;
    foo.extraBars[i].gamma = 3 * i;
  }
  foo.name = "I am a banana";
  // This is supposed to be a handle, but we fake it with an integer.
  foo.source = new core.MojoHandle(23423782);
  foo.arrayOfArrayOfBools = [
    [true], [false, true]
  ];
  foo.arrayOfBools = [
    true, false, true, false, true, false, true, true
  ];

  int name = 31;
  var header = new bindings.MessageHeader(name);
  var message = foo.serializeWithHeader(header);

  var expectedMemory = new Uint8List.fromList([
    /*  0: */   16,    0,    0,    0,    2,    0,    0,    0,
    /*  8: */   31,    0,    0,    0,    0,    0,    0,    0,
    /* 16: */   96,    0,    0,    0,   15,    0,    0,    0,
    /* 24: */ 0xD5, 0xB4, 0x12, 0x02, 0x93, 0x6E, 0x01,    0,
    /* 32: */    5,    0,    0,    0,    0,    0,    0,    0,
    /* 40: */   72,    0,    0,    0,    0,    0,    0,    0,
  ]);

  var allActualMemory = message.buffer.buffer.asUint8List();
  var actualMemory = allActualMemory.sublist(0, expectedMemory.length);
  Expect.listEquals(expectedMemory, actualMemory);

  var expectedHandles = <core.MojoHandle>[
    new core.MojoHandle(23423782),
  ];

  Expect.listEquals(expectedHandles, message.handles);

  var receivedMessage = new bindings.ServiceMessage.fromMessage(message);

  Expect.equals(receivedMessage.header.size, header.size);
  Expect.equals(receivedMessage.header.type, header.type);

  var foo2 = Foo.deserialize(receivedMessage.payload);

  Expect.equals(foo.x, foo2.x);
  Expect.equals(foo.y, foo2.y);

  Expect.equals(foo.a, foo2.a);
  Expect.equals(foo.b, foo2.b);
  Expect.equals(foo.c, foo2.c);

  Expect.equals(foo.bar.alpha, foo2.bar.alpha);
  Expect.equals(foo.bar.beta, foo2.bar.beta);
  Expect.equals(foo.bar.gamma, foo2.bar.gamma);
  Expect.equals(foo.bar.type, foo2.bar.type);
  Expect.listEquals(foo.data, foo2.data);

  for (int i = 0; i < foo2.extraBars.length; i++) {
    Expect.equals(foo.extraBars[i].alpha, foo2.extraBars[i].alpha);
    Expect.equals(foo.extraBars[i].beta, foo2.extraBars[i].beta);
    Expect.equals(foo.extraBars[i].gamma, foo2.extraBars[i].gamma);
    Expect.equals(foo.extraBars[i].type, foo2.extraBars[i].type);
  }

  Expect.equals(foo.name, foo2.name);
  Expect.equals(foo.source, foo2.source);

  Expect.listEquals(foo.arrayOfBools, foo2.arrayOfBools);
  for (int i = 0; i < foo2.arrayOfArrayOfBools.length; i++) {
    Expect.listEquals(foo.arrayOfArrayOfBools[i],
                      foo2.arrayOfArrayOfBools[i]);
  }
}


class Rect extends bindings.Struct {
  static const int kStructSize = 24;
  static const bindings.StructDataHeader kDefaultStructInfo =
      const bindings.StructDataHeader(kStructSize, 4);
  int x;
  int y;
  int width;
  int height;

  Rect() : super(kStructSize);

  static Rect deserialize(bindings.Message message) {
    return decode(new bindings.Decoder(message));
  }

  static Rect decode(bindings.Decoder decoder0) {
    if (decoder0 == null) {
      return null;
    }
    Rect result = new Rect();
    var mainDataHeader = decoder0.decodeStructDataHeader();
    if (mainDataHeader.version > 0) {
      result.x = decoder0.decodeInt32(8);
    }
    if (mainDataHeader.version > 1) {
      result.y = decoder0.decodeInt32(12);
    }
    if (mainDataHeader.version > 2) {
      result.width = decoder0.decodeInt32(16);
    }
    if (mainDataHeader.version > 3) {
      result.height = decoder0.decodeInt32(20);
    }
    return result;
  }

  void encode(bindings.Encoder encoder) {
    var encoder0 = encoder.getStructEncoderAtOffset(kDefaultStructInfo);
    encoder0.encodeInt32(x, 8);
    encoder0.encodeInt32(y, 12);
    encoder0.encodeInt32(width, 16);
    encoder0.encodeInt32(height, 20);
  }

  bool operator==(Rect other) =>
      (this.x == other.x) &&
      (this.y == other.y) &&
      (this.width == other.width) &&
      (this.height == other.height);
}


Rect createRect(int x, int y, int width, int height) {
  var r = new Rect();
  r.x = x;
  r.y = y;
  r.width = width;
  r.height = height;
  return r;
}


class NamedRegion extends bindings.Struct {
  static const int kStructSize = 24;
  static const bindings.StructDataHeader kDefaultStructInfo =
      const bindings.StructDataHeader(kStructSize, 2);
  String name;
  List<Rect> rects;

  NamedRegion() : super(kStructSize);

  static NamedRegion deserialize(bindings.Message message) {
    return decode(new bindings.Decoder(message));
  }

  static NamedRegion decode(bindings.Decoder decoder0) {
    if (decoder0 == null) {
      return null;
    }
    NamedRegion result = new NamedRegion();
    var mainDataHeader = decoder0.decodeStructDataHeader();
    if (mainDataHeader.version > 0) {
      result.name = decoder0.decodeString(8, true);
    }
    if (mainDataHeader.version > 1) {
      var decoder1 = decoder0.decodePointer(16, true);
      if (decoder1 == null) {
        result.rects = null;
      } else {
        var si1 = decoder1.decodeDataHeaderForPointerArray(
            bindings.kUnspecifiedArrayLength);
        result.rects = new List<Rect>(si1.numElements);
        for (int i1 = 0; i1 < si1.numElements; ++i1) {
          var decoder2 = decoder1.decodePointer(
              bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1,
              false);
          result.rects[i1] = Rect.decode(decoder2);
        }
      }
    }
    return result;
  }

  void encode(bindings.Encoder encoder) {
    var encoder0 = encoder.getStructEncoderAtOffset(kDefaultStructInfo);
    encoder0.encodeString(name, 8, true);
    if (rects == null) {
      encoder0.encodeNullPointer(16, true);
    } else {
      var encoder1 = encoder0.encodePointerArray(
          rects.length, 16, bindings.kUnspecifiedArrayLength);
      for (int i0 = 0; i0 < rects.length; ++i0) {
        encoder1.encodeStruct(
            rects[i0],
            bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0,
            false);
      }
    }
  }
}


testNamedRegion() {
  var r = new NamedRegion();
  r.name = "rectangle";
  r.rects = [createRect(1, 2, 3, 4), createRect(10, 20, 30, 40)];

  int name = 1;
  var header = new bindings.MessageHeader(name);
  var message = r.serializeWithHeader(header);
  var resultMessage = new bindings.ServiceMessage.fromMessage(message);
  var result = NamedRegion.deserialize(resultMessage.payload);

  Expect.equals("rectangle", result.name);
  Expect.equals(createRect(1, 2, 3, 4), result.rects[0]);
  Expect.equals(createRect(10, 20, 30, 40), result.rects[1]);
}


void testAlign() {
  List aligned = [
    0, // 0
    8, // 1
    8, // 2
    8, // 3
    8, // 4
    8, // 5
    8, // 6
    8, // 7
    8, // 8
    16, // 9
    16, // 10
    16, // 11
    16, // 12
    16, // 13
    16, // 14
    16, // 15
    16, // 16
    24, // 17
    24, // 18
    24, // 19
    24, // 20
  ];
  for (int i = 0; i < aligned.length; ++i) {
    Expect.equals(bindings.align(i), aligned[i]);
  }
}


class MojoString extends bindings.Struct {
  static const int kStructSize = 16;
  static const bindings.StructDataHeader kDefaultStructInfo =
      const bindings.StructDataHeader(kStructSize, 1);
  String string;
  MojoString() : super(kStructSize);

  static MojoString deserialize(bindings.Message message) {
    return decode(new bindings.Decoder(message));
  }

  static MojoString decode(bindings.Decoder decoder0) {
    if (decoder0 == null) {
      return null;
    }
    MojoString result = new MojoString();
    var mainDataHeader = decoder0.decodeStructDataHeader();
    result.string = decoder0.decodeString(8, false);
    return result;
  }

  void encode(bindings.Encoder encoder) {
    var encoder0 = encoder.getStructEncoderAtOffset(kDefaultStructInfo);
    encoder0.encodeString(string, 8, false);
  }
}


testUtf8() {
  var str = "B\u03ba\u1f79";  // some UCS-2 codepoints.
  var name = 42;
  var payloadSize = 24;

  var mojoString = new MojoString();
  mojoString.string = str;

  var header = new bindings.MessageHeader(name);
  var message = mojoString.serializeWithHeader(header);
  var resultMessage = new bindings.ServiceMessage.fromMessage(message);
  var result = MojoString.deserialize(resultMessage.payload);

  var expectedMemory = new Uint8List.fromList([
    /*  0: */   16,    0,    0,    0,    2,    0,    0,    0,
    /*  8: */   42,    0,    0,    0,    0,    0,    0,    0,
    /* 16: */   16,    0,    0,    0,    1,    0,    0,    0,
    /* 24: */   8,     0,    0,    0,    0,    0,    0,    0,
    /* 32: */   14,    0,    0,    0,    6,    0,    0,    0,
    /* 40: */ 0x42, 0xCE, 0xBA, 0xE1, 0xBD, 0xB9,    0,    0,
  ]);
  var allActualMemory = message.buffer.buffer.asUint8List();
  var actualMemory = allActualMemory.sublist(0, expectedMemory.length);
  Expect.equals(expectedMemory.length, actualMemory.length);
  Expect.listEquals(expectedMemory, actualMemory);

  Expect.equals(str, result.string);
}


main() {
  testAlign();
  testBar();
  testFoo();
  testNamedRegion();
  testUtf8();
}
