/*
 * Copyright 2018, TeamDev. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package io.spine.server.storage.datastore.given;

import com.google.auth.oauth2.ServiceAccountCredentials;
import com.google.cloud.NoCredentials;
import com.google.cloud.datastore.Datastore;
import com.google.cloud.datastore.DatastoreOptions;
import io.spine.logging.Logging;
import io.spine.server.storage.datastore.ProjectId;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;

import static com.google.auth.oauth2.ServiceAccountCredentials.fromStream;
/**
 * Provides test {@link Datastore} instances.
 */
public class TestDatastores {
    private static final ProjectId TEST_PROJECT_ID = ProjectId.of("spine-dev");
    /** Prevent this test utility class from being instantiated. */
    private TestDatastores() {
    }
    /**
     * Obtains Datastore instance used for testing on a developer's workstation.
     */
    public static Datastore local() {
        return Local.INSTANCE.getService();
    }
    /**
     * Obtains Datastore instance used for testing in a CI environment.
     */
    public static Datastore remote() {
        return Ci.INSTANCE.getService();
    }
    /**
     * Obtains ProjectId of the test environment.
     */
    public static ProjectId projectId() {
        return TEST_PROJECT_ID;
    }
    /**
     * Abstract base for options factories.
     */
    private abstract static class Options {
        private final DatastoreOptions.Builder builder;
        private Options() {
            builder = DatastoreOptions.newBuilder()
                                      .setProjectId(projectId().getValue());
        }
        final DatastoreOptions.Builder builder() {
            return builder;
        }
        final DatastoreOptions create() {
            return builder.build();
        }
    }
    /**
     * Local Datastore options used on developers' machines.
     */
    private static final class Local extends Options {
        private static final String DEFAULT_HOST = "localhost:8080";
        private static final DatastoreOptions INSTANCE = new Local().create();
        private Local() {
            super();
            builder().setHost(DEFAULT_HOST);
            builder().setCredentials(NoCredentials.getInstance());
        }
    }
    /**
     * Options used to run tests in CI environment, which uses connection to
     * a real Datastore instance in the testing Google Cloud environment.
     */
    @SuppressWarnings("NewClassNamingConvention")
    private static final class Ci extends Options implements Logging {
        private static final String CREDENTIALS_FILE_PATH = "/spine-dev-62685282c0b9.json";
        private static final DatastoreOptions INSTANCE = new Ci().create();
        private Ci() {
            try {
                InputStream is = TestDatastores.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
                BufferedInputStream bufferedStream = new BufferedInputStream(is);
                ServiceAccountCredentials credentials = fromStream(bufferedStream);
                builder().setCredentials(credentials);
            } catch (@SuppressWarnings("OverlyBroadCatchBlock") IOException e) {
                log().warn("Cannot find the credentials file {}.", CREDENTIALS_FILE_PATH);
            }
        }
    }
}

@@ -1005,16 +1005,17 @@
 GE.%0A */%0A
+%0A
 package 
@@ -1503,16 +1503,17 @@
 Stream;%0A
+%0A
 /**%0A * P
@@ -1584,24 +1584,25 @@
 atastores %7B%0A
+%0A
     private 
@@ -1669,16 +1669,17 @@
 -dev%22);%0A
+%0A
     /** 
@@ -1771,24 +1771,25 @@
 s() %7B%0A    %7D%0A
+%0A
     /**%0A    
@@ -1953,32 +1953,33 @@
 ervice();%0A    %7D%0A
+%0A
     /**%0A     * O
@@ -2128,32 +2128,33 @@
 ervice();%0A    %7D%0A
+%0A
     /**%0A     * O
@@ -2279,24 +2279,25 @@
 T_ID;%0A    %7D%0A
+%0A
     /**%0A    
@@ -2380,32 +2380,33 @@
 class Options %7B%0A
+%0A
         private 
@@ -2437,32 +2437,33 @@
 uilder builder;%0A
+%0A
         private 
@@ -2605,32 +2605,33 @@
 e());%0A        %7D%0A
+%0A
         final Da
@@ -2695,32 +2695,33 @@
 lder;%0A        %7D%0A
+%0A
         final Da
@@ -2790,32 +2790,33 @@
         %7D%0A    %7D%0A
+%0A
     /**%0A     * L
@@ -2931,16 +2931,17 @@
 tions %7B%0A
+%0A
         
@@ -3072,32 +3072,33 @@
 cal().create();%0A
+%0A
         private 
@@ -3252,24 +3252,25 @@
     %7D%0A    %7D%0A
+%0A
     /**%0A    
@@ -3545,16 +3545,17 @@
 gging %7B%0A
+%0A
         
@@ -3638,16 +3638,16 @@
 .json%22;%0A
-
         
@@ -3710,24 +3710,25 @@
 ).create();%0A
+%0A
         priv

Remove unintended changes in spacing