// Copyright (c) 2021, 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.
//
// SharedObjects=ffi_test_functions

// @dart = 2.9

import 'dart:ffi';

import "package:expect/expect.dart";
import 'package:ffi/ffi.dart';

// Reuse struct definitions.
import 'function_structs_by_value_generated_test.dart';

void main() {
  testSizeOf();
  testLoad();
  testLoadMultiAnnotation();
  testStore();
  testToString();
  testRange();
}

void testSizeOf() {
  Expect.equals(32, sizeOf<Struct32BytesInlineArrayMultiDimensionalInt>());
  Expect.equals(64, sizeOf<Struct64BytesInlineArrayMultiDimensionalInt>());
}

/// Tests the load of nested `Array`s.
///
/// Only stores into arrays which do not have nested arrays.
void testLoad() {
  final Pointer<Struct32BytesInlineArrayMultiDimensionalInt> pointer = calloc();
  final struct = pointer.ref;
  final array = struct.a0;
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        for (int l = 0; l < 2; l++) {
          for (int m = 0; m < 2; m++) {
            array[i][j][k][l][m] = i + j + k + l + m;
          }
        }
      }
    }
  }
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        for (int l = 0; l < 2; l++) {
          for (int m = 0; m < 2; m++) {
            Expect.equals(i + j + k + l + m, array[i][j][k][l][m]);
          }
        }
      }
    }
  }
  calloc.free(pointer);
}

/// Tests the load of nested `Array`s.
///
/// Only stores into arrays which do not have nested arrays.
void testLoadMultiAnnotation() {
  final Pointer<Struct64BytesInlineArrayMultiDimensionalInt> pointer = calloc();
  final struct = pointer.ref;
  final array = struct.a0;
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        for (int l = 0; l < 2; l++) {
          for (int m = 0; m < 2; m++) {
            for (int o = 0; o < 2; o++) {
              array[i][j][k][l][m][o] = i + j + k + l + m + o;
            }
          }
        }
      }
    }
  }
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        for (int l = 0; l < 2; l++) {
          for (int m = 0; m < 2; m++) {
            for (int o = 0; o < 2; o++) {
              Expect.equals(i + j + k + l + m + o, array[i][j][k][l][m][o]);
            }
          }
        }
      }
    }
  }
  calloc.free(pointer);
}

void testStore() {
  final Pointer<Struct32BytesInlineArrayMultiDimensionalInt> pointer = calloc();
  final struct = pointer.ref;
  final array = struct.a0;
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        for (int l = 0; l < 2; l++) {
          for (int m = 0; m < 2; m++) {
            array[i][j][k][l][m] = i + j + k + l + m;
          }
        }
      }
    }
  }
  array[0] = array[1]; // Copy many things.
  for (int j = 0; j < 2; j++) {
    for (int k = 0; k < 2; k++) {
      for (int l = 0; l < 2; l++) {
        for (int m = 0; m < 2; m++) {
          Expect.equals(array[1][j][k][l][m], array[0][j][k][l][m]);
        }
      }
    }
  }
  calloc.free(pointer);
}

// // Tests the toString of the test generator.
void testToString() {
  final Pointer<Struct32BytesInlineArrayMultiDimensionalInt> pointer = calloc();
  final struct = pointer.ref;
  final array = struct.a0;
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        for (int l = 0; l < 2; l++) {
          for (int m = 0; m < 2; m++) {
            array[i][j][k][l][m] = 16 * i + 8 * j + 4 * k + 2 * l + m;
          }
        }
      }
    }
  }
  Expect.equals(
      "([[[[[0, 1], [2, 3]], [[4, 5], [6, 7]]], [[[8, 9], [10, 11]], [[12, 13], [14, 15]]]], [[[[16, 17], [18, 19]], [[20, 21], [22, 23]]], [[[24, 25], [26, 27]], [[28, 29], [30, 31]]]]])",
      struct.toString());
  calloc.free(pointer);
}

void testRange() {
  final pointer = calloc<Struct32BytesInlineArrayMultiDimensionalInt>();
  final struct = pointer.ref;
  final array = struct.a0;
  array[0];
  array[1];
  Expect.throws(() => array[-1]);
  Expect.throws(() => array[-1] = array[1]);
  Expect.throws(() => array[2]);
  Expect.throws(() => array[2] = array[1]);
  array[0][0];
  array[0][1];
  Expect.throws(() => array[0][-1]);
  Expect.throws(() => array[0][-1] = array[0][1]);
  Expect.throws(() => array[0][2]);
  Expect.throws(() => array[0][2] = array[0][1]);
  calloc.free(pointer);
}
