// 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:mojo_bindings' as bindings;
import 'dart:mojo_core' as core;
import 'dart:typed_data';

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

class Bar extends bindings.Struct {
  static const int kStructSize = 16;
  static const bindings.DataHeader kDefaultStructInfo =
      const bindings.DataHeader(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.decodeDataHeader();
    if (mainDataHeader.numFields > 0) {
      result.alpha = decoder0.decodeUint8(8);
    }
    if (mainDataHeader.numFields > 1) {
      result.beta = decoder0.decodeUint8(9);
    }
    if (mainDataHeader.numFields > 2) {
      result.gamma = decoder0.decodeUint8(10);
    }
    if (mainDataHeader.numFields > 3) {
      result.type = decoder0.decodeInt32(12);
    }
    return result;
  }

  void encode(bindings.Encoder encoder) {
    var encoder0 = encoder.getEncoderAtOffset(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.DataHeader kDefaultStructInfo =
      const bindings.DataHeader(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.decodeDataHeader();
    if (mainDataHeader.numFields > 0) {
      result.x = decoder0.decodeInt32(8);
    }
    if (mainDataHeader.numFields > 1) {
      result.y = decoder0.decodeInt32(12);
    }
    if (mainDataHeader.numFields > 2) {
      result.a = decoder0.decodeBool(16, 0);
    }
    if (mainDataHeader.numFields > 3) {
      result.b = decoder0.decodeBool(16, 1);
    }
    if (mainDataHeader.numFields > 4) {
      result.c = decoder0.decodeBool(16, 2);
    }
    if (mainDataHeader.numFields > 9) {
      result.source = decoder0.decodeHandle(20, true);
    }
    if (mainDataHeader.numFields > 5) {
      var decoder1 = decoder0.decodePointer(24, true);
      result.bar = Bar.decode(decoder1);
    }
    if (mainDataHeader.numFields > 6) {
      result.data = decoder0.decodeUint8Array(
          32, bindings.kArrayNullable, bindings.kUnspecifiedArrayLength);
    }
    if (mainDataHeader.numFields > 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.numFields);
        for (int i1 = 0; i1 < si1.numFields; ++i1) {
          var decoder2 = decoder1.decodePointer(
              bindings.DataHeader.kHeaderSize + bindings.kPointerSize * i1,
              false);
          result.extraBars[i1] = Bar.decode(decoder2);
        }
      }
    }
    if (mainDataHeader.numFields > 8) {
      result.name = decoder0.decodeString(48, false);
    }
    if (mainDataHeader.numFields > 10) {
      result.inputStreams = decoder0.decodeHandleArray(
          56, bindings.kArrayNullable, bindings.kUnspecifiedArrayLength);
    }
    if (mainDataHeader.numFields > 11) {
      result.outputStreams = decoder0.decodeHandleArray(
          64, bindings.kArrayNullable, bindings.kUnspecifiedArrayLength);
    }
    if (mainDataHeader.numFields > 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.numFields);
        for (int i1 = 0; i1 < si1.numFields; ++i1) {
          result.arrayOfArrayOfBools[i1] = decoder1.decodeBoolArray(
              bindings.DataHeader.kHeaderSize + bindings.kPointerSize * i1,
              bindings.kNothingNullable,
              bindings.kUnspecifiedArrayLength);
        }
      }
    }
    if (mainDataHeader.numFields > 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.numFields);
        for (int i1 = 0; i1 < si1.numFields; ++i1) {
          var decoder2 = decoder1.decodePointer(
              bindings.DataHeader.kHeaderSize + bindings.kPointerSize * i1,
              false);
          {
            var si2 = decoder2.decodeDataHeaderForPointerArray(
                bindings.kUnspecifiedArrayLength);
            result.multiArrayOfStrings[i1] =
                new List<List<String>>(si2.numFields);
            for (int i2 = 0; i2 < si2.numFields; ++i2) {
              var decoder3 = decoder2.decodePointer(
                  bindings.DataHeader.kHeaderSize + bindings.kPointerSize * i2,
                  false);
              {
                var si3 = decoder3.decodeDataHeaderForPointerArray(
                    bindings.kUnspecifiedArrayLength);
                result.multiArrayOfStrings[i1][i2] =
                    new List<String>(si3.numFields);
                for (int i3 = 0; i3 < si3.numFields; ++i3) {
                  var length = bindings.DataHeader.kHeaderSize +
                               bindings.kPointerSize * i3;
                  result.multiArrayOfStrings[i1][i2][i3] =
                      decoder3.decodeString(length, false);
                }
              }
            }
          }
        }
      }
    }
    if (mainDataHeader.numFields > 14) {
      result.arrayOfBools = decoder0.decodeBoolArray(
          88, bindings.kArrayNullable, bindings.kUnspecifiedArrayLength);
    }
    return result;
  }

  void encode(bindings.Encoder encoder) {
    var encoder0 = encoder.getEncoderAtOffset(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.DataHeader.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.DataHeader.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.DataHeader.kHeaderSize + bindings.kPointerSize * i0,
              false);
        } else {
          var encoder2 = encoder1.encodePointerArray(
              multiArrayOfStrings[i0].length,
              bindings.DataHeader.kHeaderSize + bindings.kPointerSize * i0,
              bindings.kUnspecifiedArrayLength);
          for (int i1 = 0; i1 < multiArrayOfStrings[i0].length; ++i1) {
            if (multiArrayOfStrings[i0][i1] == null) {
              encoder2.encodeNullPointer(
                  bindings.DataHeader.kHeaderSize + bindings.kPointerSize * i1,
                  false);
            } else {
              var encoder3 = encoder2.encodePointerArray(
                  multiArrayOfStrings[i0][i1].length,
                  bindings.DataHeader.kHeaderSize + bindings.kPointerSize * i1,
                  bindings.kUnspecifiedArrayLength);
              for (int i2 = 0; i2 < multiArrayOfStrings[i0][i1].length; ++i2) {
                var length = bindings.DataHeader.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.DataHeader kDefaultStructInfo =
      const bindings.DataHeader(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.decodeDataHeader();
    if (mainDataHeader.numFields > 0) {
      result.x = decoder0.decodeInt32(8);
    }
    if (mainDataHeader.numFields > 1) {
      result.y = decoder0.decodeInt32(12);
    }
    if (mainDataHeader.numFields > 2) {
      result.width = decoder0.decodeInt32(16);
    }
    if (mainDataHeader.numFields > 3) {
      result.height = decoder0.decodeInt32(20);
    }
    return result;
  }

  void encode(bindings.Encoder encoder) {
    var encoder0 = encoder.getEncoderAtOffset(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.DataHeader kDefaultStructInfo =
      const bindings.DataHeader(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.decodeDataHeader();
    if (mainDataHeader.numFields > 0) {
      result.name = decoder0.decodeString(8, true);
    }
    if (mainDataHeader.numFields > 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.numFields);
        for (int i1 = 0; i1 < si1.numFields; ++i1) {
          var decoder2 = decoder1.decodePointer(
              bindings.DataHeader.kHeaderSize + bindings.kPointerSize * i1,
              false);
          result.rects[i1] = Rect.decode(decoder2);
        }
      }
    }
    return result;
  }

  void encode(bindings.Encoder encoder) {
    var encoder0 = encoder.getEncoderAtOffset(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.DataHeader.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.DataHeader kDefaultStructInfo =
      const bindings.DataHeader(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.decodeDataHeader();
    result.string = decoder0.decodeString(8, false);
    return result;
  }

  void encode(bindings.Encoder encoder) {
    var encoder0 = encoder.getEncoderAtOffset(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();
}
