// Copyright (c) 2015, 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.

library test.operation;

import 'package:plugin/plugin.dart';
import 'package:plugin/src/plugin_impl.dart';
import 'package:test/test.dart';

main() {
  group('ExtensionManager', () {
    test('processPlugins', () {
      TestPlugin plugin1 = new TestPlugin('plugin1');
      TestPlugin plugin2 = new TestPlugin('plugin1');
      ExtensionManagerImpl manager = new ExtensionManagerImpl();
      manager.processPlugins([plugin1, plugin2]);
      expect(plugin1.extensionPointsRegistered, true);
      expect(plugin1.extensionsRegistered, true);
      expect(plugin2.extensionPointsRegistered, true);
      expect(plugin2.extensionsRegistered, true);
    });

    test('registerExtension - valid', () {
      Plugin plugin = new TestPlugin('plugin');
      ExtensionManagerImpl manager = new ExtensionManagerImpl();
      ExtensionPoint point = new ExtensionPoint(plugin, 'point', null);
      manager.registerExtensionPoint(point);
      expect(point, isNotNull);
      Object extension = 'extension';
      manager.registerExtension('plugin.point', extension);
      List<Object> extensions = point.extensions;
      expect(extensions, isNotNull);
      expect(extensions, hasLength(1));
      expect(extensions[0], extension);
    });

    test('registerExtension - non existent', () {
      ExtensionManagerImpl manager = new ExtensionManagerImpl();
      expect(() => manager.registerExtension('does not exist', 'extension'),
          throwsA(new isInstanceOf<ExtensionError>()));
      ;
    });

    test('registerExtensionPoint - non-conflicting', () {
      Plugin plugin1 = new TestPlugin('plugin1');
      Plugin plugin2 = new TestPlugin('plugin2');
      ExtensionManagerImpl manager = new ExtensionManagerImpl();
      manager
          .registerExtensionPoint(new ExtensionPoint(plugin1, 'point1', null));
      manager
          .registerExtensionPoint(new ExtensionPoint(plugin1, 'point2', null));
      manager
          .registerExtensionPoint(new ExtensionPoint(plugin2, 'point1', null));
      manager
          .registerExtensionPoint(new ExtensionPoint(plugin2, 'point2', null));
    });

    test('registerExtensionPoint - conflicting - same plugin', () {
      Plugin plugin1 = new TestPlugin('plugin1');
      ExtensionManagerImpl manager = new ExtensionManagerImpl();
      manager
          .registerExtensionPoint(new ExtensionPoint(plugin1, 'point1', null));
      expect(
          () => manager.registerExtensionPoint(
              new ExtensionPoint(plugin1, 'point1', null)),
          throwsA(new isInstanceOf<ExtensionError>()));
    });

    test('registerExtensionPoint - conflicting - different plugins', () {
      Plugin plugin1 = new TestPlugin('plugin1');
      Plugin plugin2 = new TestPlugin('plugin1');
      ExtensionManagerImpl manager = new ExtensionManagerImpl();
      manager
          .registerExtensionPoint(new ExtensionPoint(plugin1, 'point1', null));
      expect(
          () => manager.registerExtensionPoint(
              new ExtensionPoint(plugin2, 'point1', null)),
          throwsA(new isInstanceOf<ExtensionError>()));
    });
  });

  group('ExtensionPointImpl', () {
    test('extensions - empty', () {
      Plugin plugin = new TestPlugin('plugin');
      ExtensionPointImpl point = new ExtensionPointImpl(plugin, 'point', null);
      List<Object> extensions = point.extensions;
      expect(extensions, isNotNull);
      expect(extensions, isEmpty);
    });

    test('uniqueIdentifier', () {
      Plugin plugin = new TestPlugin('plugin');
      ExtensionPointImpl point = new ExtensionPointImpl(plugin, 'point', null);
      expect(point.uniqueIdentifier, 'plugin.point');
    });

    test('add - single', () {
      Plugin plugin = new TestPlugin('plugin');
      ExtensionPointImpl point = new ExtensionPointImpl(plugin, 'point', null);
      Object extension = 'extension';
      point.add(extension);
      List<Object> extensions = point.extensions;
      expect(extensions, isNotNull);
      expect(extensions, hasLength(1));
      expect(extensions[0], extension);
    });

    test('add - multiple', () {
      Plugin plugin = new TestPlugin('plugin');
      ExtensionPointImpl point = new ExtensionPointImpl(plugin, 'point', null);
      point.add('extension 1');
      point.add('extension 2');
      point.add('extension 3');
      List<Object> extensions = point.extensions;
      expect(extensions, isNotNull);
      expect(extensions, hasLength(3));
    });

    test('add - with validator - valid', () {
      Plugin plugin = new TestPlugin('plugin');
      ExtensionPointImpl point =
          new ExtensionPointImpl(plugin, 'point', (Object extension) {
        if (extension is! String) {
          throw new ExtensionError('');
        }
      });
      point.add('extension');
    });

    test('add - with validator - invalid', () {
      Plugin plugin = new TestPlugin('plugin');
      ExtensionPointImpl point =
          new ExtensionPointImpl(plugin, 'point', (Object extension) {
        if (extension is! String) {
          throw new ExtensionError('');
        }
      });
      expect(() => point.add(1), throwsA(new isInstanceOf<ExtensionError>()));
    });
  });
}

/**
 * A simple plugin that can be used by tests.
 */
class TestPlugin extends Plugin {
  /**
   * A flag indicating whether the method [registerExtensionPoints] has been
   * invoked.
   */
  bool extensionPointsRegistered = false;

  /**
   * A flag indicating whether the method [registerExtensions] has been invoked.
   */
  bool extensionsRegistered = false;

  @override
  String uniqueIdentifier;

  /**
   * Initialize a newly created plugin to have the given identifier.
   */
  TestPlugin(this.uniqueIdentifier);

  @override
  void registerExtensionPoints(RegisterExtensionPoint register) {
    extensionPointsRegistered = true;
  }

  @override
  void registerExtensions(RegisterExtension register) {
    extensionsRegistered = true;
  }
}
