// Copyright (c) 2012, 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.
// Test switch statement.

// @dart = 2.9

import "package:expect/expect.dart";

class Switcher {
  Switcher() {}

  test1(val) {
    var x = 0;
    switch (val) {
      case 1:
        x = 100;
        break;
      case 2:
      case 3:
        x = 200;
        break;
      case 4:
      default:
        {
          x = 400;
          break;
        }
    }
    return x;
  }

  test2(val) {
    switch (val) {
      case 1:
        return 200;
      default:
        return 400;
    }
  }
}

class SwitchTest {
  static testMain() {
    Switcher s = new Switcher();
    Expect.equals(100, s.test1(1));
    Expect.equals(200, s.test1(2));
    Expect.equals(200, s.test1(3));
    Expect.equals(400, s.test1(4));
    Expect.equals(400, s.test1(5));

    Expect.equals(200, s.test2(1));
    Expect.equals(400, s.test2(2));
  }
}

class Enum {
  static const Enum e1 = const Enum(1);
  static const Enum e2 = const Enum(2);
  static const Enum e3 = const Enum(3);
  final int id;
  const Enum(this.id);
}

void testSwitchEnum(Enum input, int expect) {
  int result = null;
  switch (input) {
    case Enum.e1:
      result = 10;
      break;
    case Enum.e2:
      result = 20;
      break;
    case Enum.e3:
      result = 30;
      break;
    default:
      result = 40;
  }
  Expect.equals(expect, result);
}

const int ic1 = 1;
const int ic2 = 2;
void testSwitchIntExpression(int input, int expect) {
  int result = null;
  switch (input) {
    case 1 + 1: // 2
    case ic1 + 2: // 3
      result = 11;
      break;
    case ic2 * 2: // 4
    case 1 * 5: // 5
      result = 21;
      break;
    case ic1 % ic2 + 5: // 6
      result = 31;
      break;
  }
  Expect.equals(expect, result);
}

void testSwitchBool(bool input, int expect) {
  int result = null;
  switch (input) {
    case true:
      result = 12;
      break;
    case false:
      result = 22;
  }
  Expect.equals(expect, result);
}

void testSwitchString(String input, int expect) {
  int result = null;
  switch (input) {
    case 'one':
      result = 1;
      break;
    case 'two':
      result = 2;
      break;
  }
  Expect.equals(expect, result);
}

switchConstString() {
  const c = 'a';
  switch (c) {
    case 'a':
      return 'aa';
    case 'b':
      return 'bb';
    case 'c':
      return 'cc';
    case 'd':
      return 'dd';
    case 'e':
      return 'ee';
    case 'f':
      return 'ff';
  }
}

main() {
  SwitchTest.testMain();

  testSwitchEnum(Enum.e1, 10);
  testSwitchEnum(Enum.e2, 20);
  testSwitchEnum(Enum.e3, 30);
  testSwitchEnum(null, 40);

  testSwitchIntExpression(2, 11);
  testSwitchIntExpression(3, 11);
  testSwitchIntExpression(4, 21);
  testSwitchIntExpression(5, 21);
  testSwitchIntExpression(6, 31);
  testSwitchIntExpression(7, null);

  testSwitchBool(true, 12);
  testSwitchBool(false, 22);

  testSwitchString(null, null);
  testSwitchString('one', 1);
  testSwitchString('two', 2);
  testSwitchString('three', null);

  Expect.equals('aa', switchConstString());
}
