/*
 * Copyright (C) 2009-2018 Lightbend Inc. <https://www.lightbend.com>
 */

package akka.actor;

import akka.testkit.AkkaJUnitActorSystemResource;
import org.junit.*;
import akka.testkit.AkkaSpec;
import com.typesafe.config.ConfigFactory;
import org.scalatest.junit.JUnitSuite;

import static org.junit.Assert.*;

public class JavaExtension extends JUnitSuite {

  static class TestExtensionId extends AbstractExtensionId<TestExtension> implements ExtensionIdProvider {
    public final static TestExtensionId TestExtensionProvider = new TestExtensionId();

    public ExtensionId<TestExtension> lookup() {
      return TestExtensionId.TestExtensionProvider;
    }

    public TestExtension createExtension(ExtendedActorSystem i) {
      return new TestExtension(i);
    }
  }

  static class TestExtension implements Extension {
    public final ExtendedActorSystem system;

    public TestExtension(ExtendedActorSystem i) {
      system = i;
    }
  }

  static class OtherExtensionId extends AbstractExtensionId<OtherExtension> implements ExtensionIdProvider {

    public final static OtherExtensionId OtherExtensionProvider = new OtherExtensionId();

    @Override
    public ExtensionId<OtherExtension> lookup() {
      return OtherExtensionId.OtherExtensionProvider;
    }

    @Override
    public OtherExtension createExtension(ExtendedActorSystem system) {
      return new OtherExtension(system);
    }

  }

  static class OtherExtension implements Extension {
    static final ExtensionId<OtherExtension> key = OtherExtensionId.OtherExtensionProvider;

    public final ExtendedActorSystem system;

    public OtherExtension(ExtendedActorSystem system) {
      this.system = system;
    }
  }

  @ClassRule
  public static AkkaJUnitActorSystemResource actorSystemResource =
    new AkkaJUnitActorSystemResource("JavaExtension",
      ConfigFactory.parseString("akka.extensions = [ \"akka.actor.JavaExtension$TestExtensionId\" ]")
      .withFallback(AkkaSpec.testConf()));

  private final ActorSystem system = actorSystemResource.getSystem();

  @Test
  public void mustBeAccessible() {
    assertTrue(system.hasExtension((TestExtensionId.TestExtensionProvider)));
    assertSame(system.extension(TestExtensionId.TestExtensionProvider).system, system);
    assertSame(TestExtensionId.TestExtensionProvider.apply(system).system, system);
  }

  @Test
  public void mustBeAdHoc() {
    assertSame(OtherExtension.key.apply(system).system, system);
  }

}
