/*******************************************************************************
* Copyright (c) 2015 Red Hat, Inc. Distributed under license by Red Hat, Inc.
* All rights reserved. This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
* 
* Contributors: Red Hat, Inc.
******************************************************************************/

package com.openshift.internal.restclient;

import static com.openshift.internal.restclient.IntegrationTestHelper.MILLISECONDS_PER_SECOND;
import static com.openshift.internal.restclient.IntegrationTestHelper.cleanUpResource;
import static com.openshift.internal.restclient.IntegrationTestHelper.waitForResource;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.openshift.internal.restclient.model.Project;
import com.openshift.internal.restclient.model.Service;
import com.openshift.internal.restclient.model.project.OpenshiftProjectRequest;
import com.openshift.internal.restclient.model.template.Template;
import com.openshift.restclient.IClient;
import com.openshift.restclient.IResourceFactory;
import com.openshift.restclient.ResourceKind;
import com.openshift.restclient.authorization.UnauthorizedException;
import com.openshift.restclient.model.IBuildConfig;
import com.openshift.restclient.model.IProject;
import com.openshift.restclient.model.build.IBuildConfigBuilder;
import com.openshift.restclient.model.project.IProjectRequest;
import com.openshift.restclient.model.template.ITemplate;

public class DefaultClientIntegrationTest {

    private static final String VERSION = "v1";

    private static final Logger LOG = LoggerFactory.getLogger(DefaultClientIntegrationTest.class);

    private IClient client;
    private IntegrationTestHelper helper = new IntegrationTestHelper();

    private IResourceFactory factory;

    @Before
    public void setup() {
        client = helper.createClientForBasicAuth();
        factory = new ResourceFactory(client);
    }

    @Test
    public void testAuthContextIsAuthorizedWithValidUserNameAndPassword() {
        client = helper.createClient();
        client.getAuthorizationContext().setUserName(helper.getDefaultClusterAdminUser());
        client.getAuthorizationContext().setPassword(helper.getDefaultClusterAdminPassword());
        client.getAuthorizationContext().isAuthorized();
    }

    @Test(expected = UnauthorizedException.class)
    public void testAuthContextIsAuthorizedWithoutPasswordThrows() {
        client = helper.createClient();
        client.getAuthorizationContext().setUserName(helper.getDefaultClusterAdminUser());
        client.getAuthorizationContext().isAuthorized();
    }

    public void testListprojects() {
        assertTrue(client.list(ResourceKind.PROJECT, "default").size() > 0);
    }

    @Test
    public void testReady() {
        client.getServerReadyStatus();
    }

    @Test
    public void testListTemplates() {
        Template template = null;
        IProject project = null;

        try {
            OpenshiftProjectRequest projectRequest = factory.create(VERSION, ResourceKind.PROJECT_REQUEST);
            projectRequest.setName(helper.generateNamespace());
            template = factory.stub(ResourceKind.TEMPLATE, "mytemplate");

            project = (IProject) client.create(projectRequest);
            template = client.create(template, project.getNamespaceName());

            assertNotNull("Exp. the template to be found but was not", waitForResource(client, ResourceKind.TEMPLATE,
                    project.getName(), template.getName(), 5 * MILLISECONDS_PER_SECOND));

            List<ITemplate> list = client.list(ResourceKind.TEMPLATE, project.getName());
            assertEquals(1, list.size());
            for (ITemplate t : list) {
                LOG.debug(t.toString());
            }
        } finally {
            cleanUpResource(client, template);
            cleanUpResource(client, project);
        }
    }

    @Test
    public void testResourceLifeCycle() {

        IProjectRequest projectRequest = factory.create(VERSION, ResourceKind.PROJECT_REQUEST);
        ((OpenshiftProjectRequest) projectRequest).setName(helper.generateNamespace());
        LOG.debug(String.format("Stubbing project request: %s", projectRequest));

        IProjectRequest otherProjectRequest = factory.create(VERSION, ResourceKind.PROJECT_REQUEST);
        ((OpenshiftProjectRequest) otherProjectRequest).setName(helper.generateNamespace());
        LOG.debug(String.format("Stubbing project request: %s", otherProjectRequest));

        Service service = factory.create(VERSION, ResourceKind.SERVICE);
        service.setNamespace(projectRequest.getName()); // this will be the project's namespace
        service.setName("some-service");
        service.setTargetPort(6767);
        service.setPort(6767);
        service.setSelector("name", "barpod");
        LOG.debug(String.format("Stubbing service: %s", service));

        Service otherService = factory.create(VERSION, ResourceKind.SERVICE);
        otherService.setNamespace(otherProjectRequest.getName()); // this will be the project's namespace
        otherService.setName("some-other-service");
        otherService.setTargetPort(8787);
        otherService.setPort(8787);
        otherService.setSelector("name", "foopod");

        LOG.debug(String.format("Stubbing service: %s", otherService));

        IProject project = null;
        IProject other = null;
        try {
            project = (IProject) client.create(projectRequest);
            LOG.debug(String.format("Created project: %s", project));

            other = (IProject) client.create(otherProjectRequest);
            LOG.debug(String.format("Created project: %s", project));

            LOG.debug(String.format("Creating service: %s", service));
            service = client.create(service);
            LOG.debug(String.format("Created service: %s", service));

            LOG.debug(String.format("Creating service: %s", otherService));
            otherService = client.create(otherService);
            LOG.debug(String.format("Created service: %s", otherService));

            LOG.debug("Listing projects");
            List<Project> projects = client.list(ResourceKind.PROJECT);
            LOG.debug(String.format("Listed projects: %s", projects));

            LOG.debug(String.format("Listing services with namespace: %s", project.getNamespaceName()));
            List<Service> services = client.list(ResourceKind.SERVICE, project.getNamespaceName());
            LOG.debug(String.format("Listed services: %s", services));

            LOG.debug(String.format("Getting service: %s", otherService.getName()));
            Service s = client.get(ResourceKind.SERVICE, otherService.getName(), otherService.getNamespaceName());
            LOG.debug(String.format("Retrieved service: %s", s.getName()));

            assertEquals("Expected there to be only one service returned", 1, services.size());
            assertEquals("Expected to get the service with the correct name", service.getName(),
                    services.get(0).getName());

            IBuildConfigBuilder builder = client.adapt(IBuildConfigBuilder.class);
            IBuildConfig bc = builder.named("test").fromGitSource()
                    .fromGitUrl("https://github.com/openshift/origin.git").inContextDir("examples/hello-openshift")
                    .end().usingSourceStrategy().fromDockerImage("foo/bar").end().toImageStreamTag("foo/bar:latest")
                    .build();
            bc = client.create(bc, project.getNamespaceName());
            LOG.debug(String.format("Created bc: %s", bc.getName()));
            LOG.debug(String.format("Trying to delete bc: %s", bc.getName()));
            client.delete(bc);
        } finally {
            cleanUpResource(client, project);
            cleanUpResource(client, other);
            cleanUpResource(client, service);
            cleanUpResource(client, otherService);
        }

    }

}
