/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2011 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */
package org.ow2.jonas.addon.deploy.impl.deployer.service;

import org.osgi.framework.BundleContext;
import org.ow2.jonas.addon.deploy.api.deployable.IAddonDeployable;
import org.ow2.jonas.addon.deploy.api.deployer.IAddonDeployer;
import org.ow2.jonas.addon.deploy.api.deployer.IAddonDeployerLog;
import org.ow2.jonas.addon.deploy.api.deployer.IAddonService;
import org.ow2.jonas.addon.deploy.impl.cleaner.AddonCleanTask;
import org.ow2.jonas.addon.deploy.impl.deployer.AddonDeployerImpl;
import org.ow2.jonas.addon.deploy.impl.deployer.ConfDeployerImpl;
import org.ow2.jonas.addon.deploy.impl.util.AddonDeployerLog;
import org.ow2.jonas.addon.deploy.impl.util.AddonUtil;
import org.ow2.jonas.lib.service.AbsServiceImpl;
import org.ow2.jonas.lib.work.DeployerLog;
import org.ow2.jonas.management.ServiceManager;
import org.ow2.jonas.multitenant.MultitenantService;
import org.ow2.jonas.workcleaner.CleanTask;
import org.ow2.jonas.workcleaner.DeployerLogException;
import org.ow2.jonas.properties.ServerProperties;
import org.ow2.jonas.service.ServiceException;
import org.ow2.jonas.workcleaner.IDeployerLog;
import org.ow2.jonas.workcleaner.WorkCleanerService;
import org.ow2.util.ee.deploy.api.deployable.IDeployable;
import org.ow2.util.ee.deploy.api.deployer.DeployerException;
import org.ow2.util.ee.deploy.api.deployer.IDeployerManager;
import org.ow2.util.ee.deploy.api.helper.IDeployableHelper;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;
import org.ow2.util.plan.repository.api.IRepositoryManager;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Service that will register an AddonDeployerImpl
 * @author Jeremy Cazaux
 */
public class AddonDeployerComponent extends AbsServiceImpl implements IAddonService {

    /**
     * Deployer Manager. (that allow us to deploy Deployable).
     */
    private IDeployerManager deployerManager;

    /**
     * The Addon Deployer
     */
    private IAddonDeployer addonDeployer;

    /**
     * The DeployableHelper  which analyze an archive and build the associated Deployable object
     */
    private IDeployableHelper deployableHelper;

    /**
     * Server properties
     */
    private ServerProperties serverProperties;

    /**
     * The logger
     */
    private static Log logger = LogFactory.getLog(AddonDeployerComponent.class);

    /**
     * The context of the component
     */
    private BundleContext bundleContext;

    /**
     * The service manager
     */
    private ServiceManager serviceManager;

    /**
     * The addon deployer log
     */
    private IAddonDeployerLog deployerLog;

    /**
     * Logs for the workcleaner service
     */
    private IDeployerLog workCleanerLog;

    /**
     * Multitenant service
     */
    private MultitenantService multitenantService;

    /**
     * Repository manager
     */
    private IRepositoryManager repositoryManager;

    /**
     * Default constructor
     * @param bundleContext The context
     */
    public AddonDeployerComponent(final BundleContext bundleContext) {
        this.bundleContext = bundleContext;
    }

    /**
     * Start the service
     * @throws org.ow2.jonas.service.ServiceException
     */
    @Override
    protected void doStart() throws ServiceException {

        //ceate parent directory of the addons log file, if !exist
        File logFile = new File(AddonUtil.getAddonLogFile(this.serverProperties));
        if (!logFile.getParentFile().exists()) {
            logFile.getParentFile().mkdirs();
        }

        //create the addons log file
        try {
            logFile.createNewFile();
        } catch (IOException e) {
            logger.error("Cannot create the log file for addon deployer");
        }

        //create parent directory of the workcleaner log file if !exist
        File workCleanerLogFile = new File(AddonUtil.getWorkCleanerLogFile(this.serverProperties));
        if (!workCleanerLogFile.exists()) {
            workCleanerLogFile.getParentFile().mkdirs();
            try {
                workCleanerLogFile.createNewFile();
            } catch (IOException e) {
                logger.error("Cannot create the cleaner log file for addon deployer");
            }
        }

        try {
            this.deployerLog = new AddonDeployerLog(logFile);
        } catch (DeployerLogException e) {
            logger.error("Cannot create an addons log");
        }

        try {
            this.workCleanerLog = new DeployerLog(workCleanerLogFile);
        } catch (DeployerLogException e) {
            logger.error("Cannot create a workcleaner log for the addons");
        }

        //Create a new AddonDeployer
        this.addonDeployer = new AddonDeployerImpl(this.serverProperties, this.deployableHelper, this.deployerLog,
                this.deployerManager, this.bundleContext,  this.serviceManager, this.workCleanerLog,
                this.repositoryManager, new ConfDeployerImpl(this.bundleContext));
    }

    /**
     * Stop the service
     * @throws org.ow2.jonas.service.ServiceException
     */
    @Override
    protected void doStop() throws ServiceException {
        this.deployerManager.unregister(this.addonDeployer);
    }

    /**
     * @param deployerManager the {@link org.ow2.util.ee.deploy.api.deployer.IDeployerManager} to set
     */
    public void setDeployerManager(final IDeployerManager deployerManager) {
        this.deployerManager = deployerManager;
    }

    /**
     * @param serverProperties ServerProperties to set
     */
    public void setServerProperties(final ServerProperties serverProperties) {
        this.serverProperties = serverProperties;
    }

    /**
     * @param deployableHelper The DeployableHelper which analyze an archive and build the associated Deployable object
     */
    public void setDeployableHelper(final IDeployableHelper deployableHelper) {
        this.deployableHelper = deployableHelper;
    }

    /**
     * @param serviceManager The service manager to registered
     */
    public void registerServiceManager(final ServiceManager serviceManager) {
        this.serviceManager = serviceManager;
    }

    /**
     * Unregistered the service manager
     */
    public void unregisterServiceManager() {
        this.serviceManager = null;
    }

    /**
     * Method called when the workCleanerService is bound to the component.
     * @param workCleanerService the workCleanerService reference
     */
    protected void setWorkCleanerService(final WorkCleanerService workCleanerService) {
        CleanTask cleanTask = new AddonCleanTask(this.addonDeployer, this.workCleanerLog);
        workCleanerService.registerTask(cleanTask);
        workCleanerService.executeTasks();
    }

    /**
     * Set Multitenant service impl
     * @param multitenantService
     */
    protected void setMultitenantService(MultitenantService multitenantService) {
        this.addonDeployer.setMultitenantService(multitenantService);
    }

    /**
     * Unset Multitenant service impl
     */
    protected void unsetMultitenantService() {
        this.addonDeployer.unsetMultitenantService();
    }

    /**
     * Set repository manager impl
     * @param repositoryManager
     */
    protected void setRepositoryManager(IRepositoryManager repositoryManager) {
        this.repositoryManager = repositoryManager;
    }

    /**
     * Unset repository manager impl
     */
    protected void unsetRepositoryManager() {
        this.repositoryManager = null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public IDeployable<IAddonDeployable> install(final IDeployable<IAddonDeployable> deployable,
                                                 final boolean installFromACommand) throws DeployerException {
        return this.addonDeployer.install(deployable, installFromACommand);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void start(final String addonName) throws DeployerException {
        this.addonDeployer.start(addonName);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void stop(final String addonName) throws DeployerException {
        this.addonDeployer.stop(addonName);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void uninstall(final String addonName) throws DeployerException {
        this.addonDeployer.uninstall(addonName);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<IAddonDeployable> getAddons() {
        return this.addonDeployer.getAddons();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public IAddonDeployable getAddon(long addonId) {
        return this.addonDeployer.getAddon(addonId);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void resolve() {
        this.addonDeployer.resolve();
    }
}
