/**
 * Licensed to the Austrian Association for Software Tool Integration (AASTI)
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. The AASTI 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 org.openengsb.core.services.internal.deployer.connector;

import java.io.File;
import java.io.IOException;

import org.apache.felix.fileinstall.ArtifactInstaller;
import org.openengsb.core.api.ConnectorManager;
import org.openengsb.core.api.ConnectorValidationFailedException;
import org.openengsb.core.api.model.ConnectorConfiguration;
import org.openengsb.core.common.AbstractOpenEngSBService;
import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;

public class ConnectorDeployerService extends AbstractOpenEngSBService implements ArtifactInstaller {

    private static final String AUTH_PASSWORD = "password";
    private static final String AUTH_USER = "admin";
    private static final String CONNECTOR_EXTENSION = ".connector";

    private static final Logger LOGGER = LoggerFactory.getLogger(ConnectorDeployerService.class);

    private AuthenticationManager authenticationManager;
    private ConnectorManager serviceManager;

    @Override
    public boolean canHandle(File artifact) {
        LOGGER.debug("ConnectorDeployer.canHandle(\"{}\")", artifact.getAbsolutePath());

        if (artifact.isFile() && artifact.getName().endsWith(CONNECTOR_EXTENSION)) {
            LOGGER.info("Found a .connector file to deploy.");
            return true;
        }
        return false;
    }

    @Override
    public void install(File artifact) throws IOException {
        LOGGER.debug("ConnectorDeployer.install(\"{}\")", artifact.getAbsolutePath());

        ConnectorFile configFile = new ConnectorFile(artifact);
        ConnectorConfiguration newConfig = configFile.load();
        authenticate(AUTH_USER, AUTH_PASSWORD);
        if (newConfig.getContent().getProperties().get(Constants.SERVICE_RANKING) == null
                && ConnectorFile.isRootService(artifact)) {
            newConfig.getContent().getProperties().put(Constants.SERVICE_RANKING, "-1");
        }
        // log.info(String.format("Loading instance %s of connector %s", serviceId, newConfig.getConnectorType()));

        try {
            serviceManager.create(newConfig.getConnectorId(), newConfig.getContent());
        } catch (ConnectorValidationFailedException e) {
            throw new RuntimeException(e);
        }

        // TODO update
        // serviceManager.update(serviceId, newConfig.getAttributes());
        // deployerStorage.put(artifact, newConfig);
        // log.info(String.format("Connector %s of type %s valid: %b", newConfig.getConnectorType(), serviceId,
        // validationResult.isValid()));

    }

    @Override
    public void update(File artifact) throws IOException {
        LOGGER.debug("ConnectorDeployer.update(\"{}\")", artifact.getAbsolutePath());
        ConnectorConfiguration newConfig = new ConnectorFile(artifact).load();
        authenticate(AUTH_USER, AUTH_PASSWORD);
        try {
            serviceManager.update(newConfig.getConnectorId(), newConfig.getContent());
        } catch (ConnectorValidationFailedException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void uninstall(File artifact) throws Exception {
        LOGGER.debug("ConnectorDeployer.uninstall(\"{}\")", artifact.getAbsolutePath());

        try {
            authenticate(AUTH_USER, AUTH_PASSWORD);

            // log.info(String.format("Removing instance %s of connector %s", serviceId, connectorType));

            // TODO delete
            // serviceManager.delete(serviceId);
        } catch (Exception e) {
            LOGGER.error("Removing connector failed: ", e);
            throw e;
        }
    }

    private boolean authenticate(String username, String password) {
        boolean authenticated = false;
        try {
            Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
                    username, password));
            SecurityContextHolder.getContext().setAuthentication(authentication);
            authenticated = authentication.isAuthenticated();
            LOGGER.info("Connector deployer succesfully authenticated: {}", authenticated);
        } catch (AuthenticationException e) {
            LOGGER.warn("User '{}' failed to login. Reason: ", username, e);
            authenticated = false;
        }
        return authenticated;
    }

    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    public void setServiceManager(ConnectorManager serviceManager) {
        this.serviceManager = serviceManager;
    }

}

@@ -3125,82 +3125,41 @@
     
-// log.info(String.format(%22Loading instance %25s of connector %25s%22, serviceId
+LOGGER.info(%22Loading instance %7B%7D%22
 , ne
@@ -3178,22 +3178,19 @@
 onnector
-Type()
+Id(
 ));%0A%0A   
@@ -3401,311 +3401,8 @@
   %7D%0A
-%0A        // TODO update%0A        // serviceManager.update(serviceId, newConfig.getAttributes());%0A        // deployerStorage.put(artifact, newConfig);%0A        // log.info(String.format(%22Connector %25s of type %25s valid: %25b%22, newConfig.getConnectorType(), serviceId,%0A        // validationResult.isValid()));%0A%0A
     
@@ -4063,33 +4063,32 @@
 bsolutePath());%0A
-%0A
         try %7B%0A  
@@ -4077,32 +4077,32 @@
 ;%0A        try %7B%0A
+
             auth
@@ -4137,17 +4137,16 @@
 SWORD);%0A
-%0A
         

remove some commented code