#!/usr/bin/env dart
// Copyright (c) 2019, 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.

import 'dart:convert';
import 'package:protobuf/protobuf.dart';
import 'package:test/test.dart';
import 'package:fixnum/fixnum.dart' show Int64;
import '../out/protos/foo.pb.dart';
import '../out/protos/google/protobuf/unittest.pb.dart';

void main() {
  group('frozen and tobuilder', () {
    var original = Outer()
      ..inner = (Inner()..value = 'foo')
      ..inners.add(Inner()..value = 'repeatedInner')
      ..setExtension(FooExt.inner, Inner()..value = 'extension')
      ..getExtension(FooExt.inners).add(Inner()..value = 'repeatedExtension')
      ..freeze();
    test('can read extensions', () {
      expect(original.getExtension(FooExt.inner).value, 'extension');
      expect(
          original.getExtension(FooExt.inners)[0].value, 'repeatedExtension');
    });

    test('frozen message cannot be modified', () {
      expect(() => original.inner = (Inner()..value = 'bar'),
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => original.inner..value = 'bar',
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => original.inners.add(Inner()..value = 'bar'),
          throwsA(TypeMatcher<UnsupportedError>()));
    });

    test('extensions cannot be modified', () {
      expect(() => original.setExtension(FooExt.inner, Inner()..value = 'bar'),
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => original.getExtension(FooExt.inner).value = 'bar',
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(
          () =>
              original.getExtension(FooExt.inners).add(Inner()..value = 'bar'),
          throwsA(TypeMatcher<UnsupportedError>()));
    });

    Outer builder = original.toBuilder();
    test('builder is a shallow copy', () {
      expect(builder.inner, same(original.inner));
    });
    test('builder extensions are also copied shallowly', () {
      expect(builder.getExtension(FooExt.inner),
          same(original.getExtension(FooExt.inner)));
    });

    test('repeated fields are cloned', () {
      expect(builder.inners, isNot(same(original.inners)));
      expect(builder.inners[0], same(original.inners[0]));
    });

    test('repeated extensions are cloned', () {
      expect(builder.getExtension(FooExt.inners),
          isNot(same(original.getExtension(FooExt.inners))));
      expect(builder.getExtension(FooExt.inners)[0],
          same(original.getExtension(FooExt.inners)[0]));
    });

    test(
        'the builder is only a shallow copy, the nested message is still frozen.',
        () {
      expect(() => builder.inner.value = 'bar',
          throwsA(TypeMatcher<UnsupportedError>()));
    });
    test('the builder is mutable', () {
      builder.inner = (Inner()..value = 'zop');
      expect(builder.inner.value, 'zop');
      builder.inners.add(Inner()..value = 'bob');
      expect(builder.inners.length, 2);
      builder.setExtension(FooExt.inner, Inner()..value = 'nob');
      expect(builder.getExtension(FooExt.inner).value, 'nob');
      builder.getExtension(FooExt.inners).add(Inner()..value = 'rob');
      expect(builder.getExtension(FooExt.inners).length, 2);
    });
    test('newly created `Inner` is mutable', () {
      builder.inner.value = 'bar';
      expect(builder.inner.value, 'bar');
    });
  });

  group('map properties behave correctly', () {
    OuterWithMap original;
    OuterWithMap outerBuilder;
    setUp(() {
      original = OuterWithMap()
        ..innerMap[1] = (Inner()..value = 'mapInner')
        ..freeze();
      outerBuilder = original.toBuilder();
    });
    test('map fields are cloned', () {
      expect(outerBuilder.innerMap, isNot(same(original.innerMap)));
      expect(outerBuilder.innerMap[1], same(original.innerMap[1]));
    });
    test('the builder is mutable', () {
      outerBuilder.innerMap[1] = (Inner()..value = 'mob');
      expect(outerBuilder.innerMap[1].value, 'mob');
    });
  });

  group('frozen unknown fields', () {
    Inner inner;
    TestEmptyMessage emptyMessage;
    int tagNumber;
    UnknownFieldSet unknownFieldSet;
    UnknownFieldSetField field;

    setUp(() {
      inner = Inner()..value = 'bob';
      emptyMessage = TestEmptyMessage.fromBuffer(inner.writeToBuffer());
      tagNumber = inner.getTagNumber('value');
      unknownFieldSet = emptyMessage.unknownFields;
      field = unknownFieldSet.getField(tagNumber);
    });

    test('can read from a frozen unknown fieldset', () {
      expect(unknownFieldSet.hasField(tagNumber), isTrue);
      expect(field.lengthDelimited[0], utf8.encode(inner.value));

      emptyMessage.freeze();
      unknownFieldSet = emptyMessage.unknownFields;
      field = unknownFieldSet.getField(tagNumber);

      expect(unknownFieldSet.hasField(tagNumber), isTrue);
      expect(field.lengthDelimited[0], utf8.encode(inner.value));
    });

    test('can add fields to a builder with unknown fields', () {
      emptyMessage.freeze();
      TestEmptyMessage builder = emptyMessage.toBuilder();

      builder.unknownFields
          .addField(2, UnknownFieldSetField()..fixed32s.add(42));
      expect(builder.unknownFields.getField(2).fixed32s[0], 42);
    });

    test('cannot mutate already added UnknownFieldSetField on builder', () {
      emptyMessage.freeze();
      TestEmptyMessage builder = emptyMessage.toBuilder();

      expect(
          () => builder.unknownFields.getField(1).lengthDelimited[0] =
              utf8.encode('alice'),
          throwsA(TypeMatcher<UnsupportedError>()));
    });

    test('cannot add to a frozen UnknownFieldSetField', () {
      emptyMessage.freeze();

      expect(
          () => field.addFixed32(1), throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => field.fixed32s.add(1),
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => field.addFixed64(Int64(1)),
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => field.fixed64s.add(Int64(1)),
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => field.addLengthDelimited([1]),
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => field.lengthDelimited.add([1]),
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => field.addGroup(unknownFieldSet.clone()),
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => field.groups.add(unknownFieldSet.clone()),
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => field.addVarint(Int64(1)),
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => field.varints.add(Int64(1)),
          throwsA(TypeMatcher<UnsupportedError>()));
    });

    test('cannot add or merge field to a frozen UnknownFieldSet', () {
      emptyMessage.freeze();

      expect(() => unknownFieldSet.addField(2, field),
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => unknownFieldSet.mergeField(2, field),
          throwsA(TypeMatcher<UnsupportedError>()));
    });

    test('cannot merge message into a frozen UnknownFieldSet', () {
      emptyMessage.freeze();
      var other = emptyMessage.deepCopy();

      expect(() => emptyMessage.mergeFromBuffer(other.writeToBuffer()),
          throwsA(TypeMatcher<UnsupportedError>()));
      expect(() => emptyMessage.mergeFromMessage(other),
          throwsA(TypeMatcher<UnsupportedError>()));
    });

    test('cannot add a field to a frozen UnknownFieldSet', () {
      emptyMessage.freeze();

      expect(() => unknownFieldSet.addField(tagNumber, field),
          throwsA(TypeMatcher<UnsupportedError>()));
    });
  });
}
