<%#
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *
-%>
package <%= polygene.packageName %>.app;

import <%= polygene.packageName %>.bootstrap.<%= polygene.name %>ApplicationAssembler;

import <%= polygene.packageName %>.bootstrap.config.ConfigModule;
import <%= polygene.packageName %>.bootstrap.config.ConfigurationLayer;
import javax.json.Json;
import javax.json.JsonWriter;

import org.apache.polygene.api.structure.Application;
import org.apache.polygene.api.structure.ApplicationDescriptor;
import org.apache.polygene.bootstrap.ApplicationAssembly;
import org.apache.polygene.bootstrap.AssemblyException;
import org.apache.polygene.bootstrap.ModuleAssembly;
import org.apache.polygene.bootstrap.layered.LayeredApplicationAssembler;
import org.apache.polygene.tools.model.descriptor.ApplicationDetailDescriptor;
import org.apache.polygene.tools.model.descriptor.ApplicationDetailDescriptorBuilder;
<%
polygene.needsDelayChecker = false;
polygene.needsDocker = ['Cassandra', 'JClouds', 'MySQL', 'PostgreSQL', 'Redis', 'Riak'].indexOf(polygene.entitystore) != -1 || ['Memcache'].indexOf(polygene.caching) != -1;

if( polygene.entitystore === 'MySQL' ) {
%>import java.util.HashMap;
<%
}
if( polygene.entitystore !== 'Memory' && polygene.entitystore !== 'Preferences' ) {
    if( polygene.entitystore.indexOf('SQL') < 0 ) {
%>import org.apache.polygene.entitystore.<%= polygene.entitystore.toLowerCase() %>.<%= polygene.entitystore %>EntityStoreConfiguration;
<% } else {
%>import org.apache.polygene.entitystore.sql.SQLEntityStoreConfiguration;
<%
    }
}
if( polygene.caching === 'Memcache' ) {
%>import org.apache.polygene.cache.memcache.MemcacheConfiguration;
<%
}
if( polygene.needsDocker ) {
%>
import com.spotify.docker.client.DefaultDockerClient;
import pl.domzal.junit.docker.rule.DockerRule;
import pl.domzal.junit.docker.rule.DockerRuleBuilder;
import pl.domzal.junit.docker.rule.WaitFor;
import pl.domzal.junit.docker.rule.wait.StartCondition;
import pl.domzal.junit.docker.rule.wait.StartConditionCheck;

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.junit.Assume;
import org.junit.ClassRule;
<%
}
%>
import org.junit.Ignore;
import org.junit.Test;

public class BootstrapTest
{
    @Test @Ignore( "TODO: Testcase doesn't work for all combinations yet. Docker issues?" )
    public void applicationBootstrapSucceeds()
        throws Exception
    {
        <%= polygene.name %>Launcher launcher = new <%= polygene.name %>Launcher()
        {
            @Override
            protected LayeredApplicationAssembler createApplicationAssembler()
                throws AssemblyException
            {
<% if( polygene.hasFeature( 'security' ) ) {
%>                DevelopmentKeyManagement.initializeKeyStore();
<% }
%>                return new <%= polygene.name %>ApplicationAssembler( "LaunchTest", "0", Application.Mode.development, BootstrapTest.this::setupTest )
                {
                    @Override
                    protected void onModelCreated( ApplicationDescriptor model )
                    {
                        ApplicationDetailDescriptor modelDescription = ApplicationDetailDescriptorBuilder.createApplicationDetailDescriptor( model );
                        System.out.println( "Application Model" );
                        JsonWriter writer = Json.createWriter( System.out );
                        System.out.println();
                        writer.writeObject( modelDescription.toJson() );
                        super.onModelCreated( model );
                    }
                };
            }
        };
        launcher.initialize();
        System.out.println("Application Launched...");
        // Thread.sleep( 3600000L );
        launcher.shutdown();
    }

    private void setupTest( ApplicationAssembly assembly )
    {
        entityStoreSetup( assembly );
<%
if( polygene.caching === 'Memcache' ) {
%>
        cacheSetup( assembly );
<%
}
%>
    }
<%
if(  polygene.entitystore === 'Cassandra' ) {
%>
    private void entityStoreSetup( ApplicationAssembly assembly )
    {
        ModuleAssembly config = assembly.layer( ConfigurationLayer.NAME ).module( ConfigModule.NAME );
        CassandraEntityStoreConfiguration defaults = config.forMixin( CassandraEntityStoreConfiguration.class ).declareDefaults();
        String host = ES_DOCKER.getDockerHost();
        int port = Integer.valueOf( ES_DOCKER.getExposedContainerPort( "9042/tcp" ) );
        System.out.println("Cassandra: " + host + ":" + port);
        defaults.hostnames().set( host + ':' + port );
        defaults.createIfMissing().set( true );
    }

    @ClassRule
    public static final OptionalDockerRule ES_DOCKER = new OptionalDockerRule( DockerRule.builder()
                                                         .imageName( "cassandra:latest"  )
                                                         .publishAllPorts( true )
                                                         .waitForTimeout( 120 )
                                                         .waitFor( WaitFor.logMessageSequence( "Starting listening for CQL clients" ) ) );
<% }
if(  polygene.entitystore === 'DerbySQL' ) {
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }
<% }
if(  polygene.entitystore === 'File' ) {
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }
<% }
if(  polygene.entitystore === 'Geode' ) {
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }
<% }
if(  polygene.entitystore === 'H2SQL' ) {
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }
<% }
if(  polygene.entitystore === 'Hazelcast' ) {
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }
<% }
if(  polygene.entitystore === 'JClouds' ) {
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }

    @ClassRule
    public static final OptionalDockerRule ES_DOCKER = new OptionalDockerRule( DockerRule.builder()
                                                         .imageName( "scality/s3server:latest"  )
                                                         .publishAllPorts( true )
                                                         .waitForTimeout( 120 )
                                                         .waitFor( WaitFor.logMessageSequence( "server started" ) ) );
<% }
if(  polygene.entitystore === 'Jdbm' ) {
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }
<% }
if(  polygene.entitystore === 'LevelDB' ) {
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }
<% }
if(  polygene.entitystore === 'Memory' ) {
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }
<% }
if(  polygene.entitystore === 'MongoDB' ) {
%>
    private void entityStoreSetup( ApplicationAssembly assembly )
    {
        ModuleAssembly config = assembly.layer( ConfigurationLayer.NAME ).module( ConfigModule.NAME );
        MongoDBEntityStoreConfiguration mongoConfig = config.forMixin( MongoDBEntityStoreConfiguration.class ).declareDefaults();
        mongoConfig.hostname().set( ES_DOCKER.getDockerHost() );
        mongoConfig.port().set( Integer.valueOf( ES_DOCKER.getExposedContainerPort( "27017/tcp" ) ) );
    }

    @ClassRule
    public static final OptionalDockerRule ES_DOCKER = new OptionalDockerRule( DockerRule.builder()
                                                            .imageName( "mongo:3.5.8" )
                                                            .expose( "27017" )
                                                            .waitForTimeout( 120 )
                                                            .waitFor( WaitFor.tcpPort(27017) ) );
<% }
if(  polygene.entitystore === 'MySQL' ) {
    polygene.needsDelayChecker = true;
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }

    @ClassRule
    public static final OptionalDockerRule ES_DOCKER = new OptionalDockerRule( DockerRule.builder()
                                                         .imageName( "mariadb:latest"  )
                                                         .publishAllPorts( true )
                                                         .waitForTimeout( 120 )
                                                         .env("MYSQL_ROOT_PASSWORD", "")
                                                         .env("MYSQL_ALLOW_EMPTY_PASSWORD", "yes")
                                                         .env("MYSQL_DATABASE", "jdbc_test_db")
                                                         .env("MYSQL_ROOT_HOST", "172.17.0.1")
//                                                       .waitFor( WaitFor.logMessageSequence( "mysqld: ready for connections" ) )   TODO: add this after next release of tdomzal/junit-docker-rule
                                                         .waitFor( new DelayChecker( 30000L ) ) );
<% }
if(  polygene.entitystore === 'PostgreSQL' ) {
    polygene.needsDelayChecker = true;
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }

    @ClassRule
    public static final OptionalDockerRule ES_DOCKER = new OptionalDockerRule( DockerRule.builder()
                                                         .imageName( "<%= polygene.packagename %>-postgresql"  )
                                                         .publishAllPorts( true )
                                                         .waitForTimeout( 120 )
                                                         .waitFor( WaitFor.logMessageSequence( "PostgreSQL init process complete; ready for start up." ) )
                                                         .waitFor( new DelayChecker( 3000L ) ) );
<% }
if(  polygene.entitystore === 'Preferences' ) {
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }
<% }
if(  polygene.entitystore === 'Redis' ) {
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }

    @ClassRule
    public static final OptionalDockerRule ES_DOCKER = new OptionalDockerRule( DockerRule.builder()
                                                         .imageName( "redis:latest"  )
                                                         .publishAllPorts( true )
                                                         .waitForTimeout( 120 )
                                                         .waitFor( pl.domzal.junit.docker.rule.WaitFor.tcpPort( 6379 ) ) );
<% }
if(  polygene.entitystore === 'Riak' ) {
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }

    @ClassRule
    public static final OptionalDockerRule ES_DOCKER = new OptionalDockerRule( DockerRule.builder()
                                                         .imageName( "basho/riak-kv:latest"  )
                                                         .publishAllPorts( true )
                                                         .waitForTimeout( 120 )
                                                         .waitFor( WaitFor.logMessageSequence( "riak_auth_mods started on node" ) ) );
<% }
if(  polygene.entitystore === 'SQLite' ) {
%>
    private void entityStoreSetup(ApplicationAssembly assembly )
    {
    }
<% }
if( polygene.caching === 'Memcache' ) {
%>

    private void cacheSetup( ApplicationAssembly assembly )
    {
        ModuleAssembly config = assembly.layer( ConfigurationLayer.NAME ).module( ConfigModule.NAME );

        MemcacheConfiguration memcacheConfig = config.forMixin( MemcacheConfiguration.class ).declareDefaults();
        memcacheConfig.addresses().set( CACHE_DOCKER.getDockerHost() + ":" + CACHE_DOCKER.getExposedContainerPort( "11211/tcp" ) );
    }

    @ClassRule
    public static final OptionalDockerRule CACHE_DOCKER = new OptionalDockerRule( DockerRule.builder()
                                                              .imageName( "memcached:1.4.36-alpine"  )
                                                              .expose( "11211" )
                                                              .waitForTimeout( 120 )
                                                              .waitFor( WaitFor.tcpPort( 11211 ) ) );

<%
}
%>

<%
if( polygene.needsDocker ) {
%>
    /**
     * This JUnit Rule will skip tests if no Docker service is available.
     */
    private static class OptionalDockerRule implements TestRule
    {
        private final DockerRuleBuilder dockerRuleBuilder;
        private DockerRule dockerRule;

        private OptionalDockerRule( DockerRuleBuilder dockerRuleBuilder )
        {
            this.dockerRuleBuilder = dockerRuleBuilder;
        }

        @Override
        public Statement apply( Statement base, Description description )
        {
            try
            {
                DefaultDockerClient.fromEnv().build().listImages();
            }
            catch( Throwable ex )
            {
                Assume.assumeNoException( ex );
            }

            dockerRule = dockerRuleBuilder.build();
            return dockerRule.apply( base, description );
        }

        public String getDockerHost()
        {
            return dockerRule.getDockerHost();
        }

        public String getExposedContainerPort( String containerPort )
        {
            return dockerRule.getExposedContainerPort( containerPort );
        }
    }
<%
}
%>

<%
if( polygene.needsDelayChecker ) {
%>
    private static class DelayChecker
        implements StartCondition
    {
        private final long millis;
        private final long doneAt;

        DelayChecker( long millis )
        {
            this.millis = millis;
            this.doneAt = System.currentTimeMillis() + millis;
        }

        @Override
        public StartConditionCheck build( DockerRule currentRule )
        {
            return new StartConditionCheck()
            {
                @Override
                public boolean check()
                {
                    return System.currentTimeMillis() > doneAt;
                }

                @Override
                public String describe()
                {
                    return String.format( "delay check %d ms", millis );
                }

                @Override
                public void after()
                {
                }
            };
        }
    }
<% }
%>}
