/*
 * 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 org.apache.ace.webui.vaadin;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.ace.authentication.api.AuthenticationService;
import org.apache.ace.client.repository.RepositoryAdmin;
import org.apache.ace.client.repository.RepositoryAdminLoginContext;
import org.apache.ace.client.repository.RepositoryObject;
import org.apache.ace.client.repository.SessionFactory;
import org.apache.ace.client.repository.helper.bundle.BundleHelper;
import org.apache.ace.client.repository.object.Artifact2FeatureAssociation;
import org.apache.ace.client.repository.object.ArtifactObject;
import org.apache.ace.client.repository.object.Distribution2TargetAssociation;
import org.apache.ace.client.repository.object.DistributionObject;
import org.apache.ace.client.repository.object.Feature2DistributionAssociation;
import org.apache.ace.client.repository.object.FeatureObject;
import org.apache.ace.client.repository.object.TargetObject;
import org.apache.ace.client.repository.repository.Artifact2FeatureAssociationRepository;
import org.apache.ace.client.repository.repository.ArtifactRepository;
import org.apache.ace.client.repository.repository.ArtifactRepository.ArtifactAlreadyExistsException;
import org.apache.ace.client.repository.repository.Distribution2TargetAssociationRepository;
import org.apache.ace.client.repository.repository.DistributionRepository;
import org.apache.ace.client.repository.repository.Feature2DistributionAssociationRepository;
import org.apache.ace.client.repository.repository.FeatureRepository;
import org.apache.ace.client.repository.repository.TargetRepository;
import org.apache.ace.client.repository.stateful.StatefulTargetObject;
import org.apache.ace.client.repository.stateful.StatefulTargetRepository;
import org.apache.ace.connectionfactory.ConnectionFactory;
import org.apache.ace.webui.NamedObject;
import org.apache.ace.webui.UIExtensionFactory;
import org.apache.ace.webui.domain.NamedStatefulTargetObject;
import org.apache.ace.webui.domain.NamedTargetObject;
import org.apache.ace.webui.vaadin.LoginWindow.LoginFunction;
import org.apache.ace.webui.vaadin.UploadHelper.ArtifactDropHandler;
import org.apache.ace.webui.vaadin.UploadHelper.GenericUploadHandler;
import org.apache.ace.webui.vaadin.UploadHelper.UploadHandle;
import org.apache.ace.webui.vaadin.component.ArtifactsPanel;
import org.apache.ace.webui.vaadin.component.AssociationHelper;
import org.apache.ace.webui.vaadin.component.DistributionsPanel;
import org.apache.ace.webui.vaadin.component.FeaturesPanel;
import org.apache.ace.webui.vaadin.component.MainActionToolbar;
import org.apache.ace.webui.vaadin.component.StatusLine;
import org.apache.ace.webui.vaadin.component.TargetsPanel;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
import org.osgi.service.log.LogService;
import org.osgi.service.useradmin.Authorization;
import org.osgi.service.useradmin.User;
import org.osgi.service.useradmin.UserAdmin;

import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.event.ShortcutAction.ModifierKey;
import com.vaadin.service.ApplicationContext;
import com.vaadin.terminal.gwt.server.WebApplicationContext;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.DragAndDropWrapper;
import com.vaadin.ui.DragAndDropWrapper.DragStartMode;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.ProgressIndicator;
import com.vaadin.ui.Window;
import com.vaadin.ui.Window.Notification;

/**
 * Main application entry point.
 */
public class VaadinClient extends com.vaadin.Application implements AssociationManager, LoginFunction {

    // basic session ID generator
    private static long generateSessionID() {
        return SESSION_ID.getAndIncrement();
    }

    /**
     * Remove the given directory and all it's files and subdirectories
     *
     * @param directory
     *            the name of the directory to remove
     */
    private static void removeDirectoryWithContent(File directory) {
        if ((directory == null) || !directory.exists()) {
            return;
        }
        File[] filesAndSubDirs = directory.listFiles();
        for (int i = 0; i < filesAndSubDirs.length; i++) {
            File file = filesAndSubDirs[i];
            if (file.isDirectory()) {
                removeDirectoryWithContent(file);
            }
            // else just remove the file
            file.delete();
        }
        directory.delete();
    }

    private static final long serialVersionUID = 1L;
    private static final AtomicLong SESSION_ID = new AtomicLong(1L);
    private static final String targetRepo = "target";
    private static final String shopRepo = "shop";

    private static final String deployRepo = "deployment";

    private static final String customerName = "apache";

    private static final String endpoint = "/repository";

    private volatile AuthenticationService m_authenticationService;
    private volatile BundleContext m_context;
    private volatile SessionFactory m_sessionFactory;
    private volatile UserAdmin m_userAdmin;
    private volatile ArtifactRepository m_artifactRepository;
    private volatile FeatureRepository m_featureRepository;
    private volatile DistributionRepository m_distributionRepository;
    private volatile StatefulTargetRepository m_statefulTargetRepository;
    private volatile TargetRepository m_targetRepository;
    private volatile Artifact2FeatureAssociationRepository m_artifact2featureAssociationRepository;
    private volatile Feature2DistributionAssociationRepository m_feature2distributionAssociationRepository;
    private volatile Distribution2TargetAssociationRepository m_distribution2targetAssociationRepository;

    private volatile RepositoryAdmin m_admin;
    private volatile LogService m_log;
    private volatile ConnectionFactory m_connectionFactory;

    private String m_sessionID;

    private ArtifactsPanel m_artifactsPanel;
    private FeaturesPanel m_featuresPanel;
    private DistributionsPanel m_distributionsPanel;
    private TargetsPanel m_targetsPanel;
    private GridLayout m_grid;
    private StatusLine m_statusLine;
    private File m_sessionDir; // private folder for session info
    private HorizontalLayout m_artifactToolbar;
    private HorizontalLayout m_featureToolbar;
    private HorizontalLayout m_distributionToolbar;
    private HorizontalLayout m_targetToolbar;
    private Window m_mainWindow;
    private final URL m_obrUrl;
    private final String m_repositoryXML;

    private final URL m_repository;
    private final boolean m_useAuth;
    private final String m_userName;
    private final AssociationHelper m_associations = new AssociationHelper();
    private final AtomicBoolean m_dependenciesResolved = new AtomicBoolean(false);
    // for the artifacts list...
    private final double m_cacheRate;
    private final int m_pageLength;

    private ProgressIndicator m_progress;

    private DependencyManager m_manager;

    private Component m_component;

    private final List<Component> m_eventHandlers = new ArrayList<>();

    private GridLayout m_mainToolbar;

    /**
     * Creates a new {@link VaadinClient} instance.
     *
     * @param m_manager2
     *
     * @param aceHost
     *            the hostname where the management service can be reached;
     * @param obrUrl
     *            the URL of the OBR to use;
     * @param useAuth
     *            <code>true</code> to use authentication, <code>false</code> to disable authentication;
     * @param userName
     *            the hardcoded username to use when authentication is disabled.
     */
    public VaadinClient(DependencyManager manager, URL aceHost, URL obrUrl, String repositoryXML, boolean useAuth, String userName, String password, double cacheRate, int pageLength) {
        m_manager = manager;
        try {
            m_repository = new URL(aceHost, endpoint);
        }
        catch (MalformedURLException e) {
            throw new IllegalArgumentException("Need a valid repository URL!", e);
        }
        m_obrUrl = obrUrl;
        m_repositoryXML = repositoryXML;
        m_useAuth = useAuth;
        m_userName = userName;
        m_cacheRate = cacheRate;
        m_pageLength = pageLength;

        if (!m_useAuth && (m_userName == null || "".equals(m_userName.trim()))) {
            throw new IllegalArgumentException("Need a valid user name when no authentication is used!");
        }
    }

    @Override
    public void close() {
        if (isRunning()) {
            m_admin.deleteLocal();
            cleanupListeners();
            m_manager.remove(m_component);
            super.close();
        }
    }

    @Override
    public Artifact2FeatureAssociation createArtifact2FeatureAssociation(String artifactId, String featureId) {
        boolean dynamicRelation = false;

        FeatureObject feature = m_featureRepository.get(featureId);
        ArtifactObject artifact = m_artifactRepository.get(artifactId);
        if (artifact == null) {
            // Maybe a BSN?
            try {
                List<ArtifactObject> artifacts = m_artifactRepository.get(FrameworkUtil.createFilter(String.format("(%s=%s)", Constants.BUNDLE_SYMBOLICNAME, artifactId)));
                if (artifacts != null && artifacts.size() > 0) {
                    dynamicRelation = true;
                    // we only need this artifact for creating the association, so it does not matter which one we
                    // take...
                    artifact = artifacts.get(0);
                }
            }
            catch (InvalidSyntaxException exception) {
                m_log.log(LogService.LOG_ERROR, "Invalid filter syntax?!", exception);
            }
        }

        // Make sure we didn't drop on a resource processor bundle...
        if (artifact != null && artifact.getAttribute(BundleHelper.KEY_RESOURCE_PROCESSOR_PID) != null) {
            // if you drop on a resource processor, and try to get it, you
            // will get null because you cannot associate anything with a
            // resource processor so we check for null here
            return null;
        }

        Artifact2FeatureAssociation result = null;
        if (artifact != null) {
            if (dynamicRelation) {
                Map<String, String> properties = Collections.singletonMap(BundleHelper.KEY_ASSOCIATION_VERSIONSTATEMENT, "0.0.0");
                result = m_artifact2featureAssociationRepository.create(artifact, properties, feature, null);
            }
            else {
                result = m_artifact2featureAssociationRepository.create(artifact, feature);
            }
        }
        return result;
    }

    @Override
    public Distribution2TargetAssociation createDistribution2TargetAssociation(String distributionId, String targetId) {
        DistributionObject distribution = m_distributionRepository.get(distributionId);
        StatefulTargetObject target = m_statefulTargetRepository.get(targetId);
        if (!target.isRegistered()) {
            target.register();
            target.setAutoApprove(true);
        }
        return m_distribution2targetAssociationRepository.create(distribution, target.getTargetObject());
    }

    @Override
    public Feature2DistributionAssociation createFeature2DistributionAssociation(String featureId, String distributionId) {
        FeatureObject feature = m_featureRepository.get(featureId);
        DistributionObject distribution = m_distributionRepository.get(distributionId);
        return m_feature2distributionAssociationRepository.create(feature, distribution);
    }

    public void destroyDependencies() {
        m_sessionFactory.destroySession(m_sessionID);
        removeDirectoryWithContent(m_sessionDir);
    }

    public void init() {
        setTheme("ace");

        if (!m_dependenciesResolved.get()) {
            final Window message = new Window("Apache ACE");
            message.getContent().setSizeFull();
            setMainWindow(message);

            Label richText = new Label("<h1>Apache ACE User Interface</h1>"
                + "<p>Due to missing component dependencies on the server, probably due to misconfiguration, "
                + "the user interface cannot be properly started. Please contact your server administrator. "
                + "You can retry accessing the user interface by <a href=\"?restartApplication\">following this link</a>.</p>");
            richText.setContentMode(Label.CONTENT_XHTML);

            // TODO we might want to add some more details here as to what's
            // missing on the other hand, the user probably can't fix that anyway
            message.addComponent(richText);
            return;
        }

        m_mainWindow = new Window("Apache ACE");
        m_mainWindow.getContent().setSizeFull();
        m_mainWindow.setBorder(Window.BORDER_NONE);

        setMainWindow(m_mainWindow);

        // Authenticate the user either by showing a login window; or by another means...
        authenticate();
    }

    /**
     * {@inheritDoc}
     */
    public boolean login(String username, String password) {
        setUser(m_authenticationService.authenticate(username, password));
        return doLogin();
    }

    /**
     * {@inheritDoc}
     */
    public void removeAssociation(Artifact2FeatureAssociation association) {
        m_artifact2featureAssociationRepository.remove(association);
    }

    /**
     * {@inheritDoc}
     */
    public void removeAssociation(Distribution2TargetAssociation association) {
        m_distribution2targetAssociationRepository.remove(association);
    }

    /**
     * {@inheritDoc}
     */
    public void removeAssociation(Feature2DistributionAssociation association) {
        m_feature2distributionAssociationRepository.remove(association);
    }

    public void setupDependencies(Component component) {
        m_sessionID = "web-" + generateSessionID();
        File dir = m_context.getDataFile(m_sessionID);
        dir.mkdir();
        m_sessionDir = dir.getAbsoluteFile();
        m_sessionFactory.createSession(m_sessionID, null);
        addSessionDependency(component, RepositoryAdmin.class);
        addSessionDependency(component, DistributionRepository.class);
        addSessionDependency(component, ArtifactRepository.class);
        addSessionDependency(component, FeatureRepository.class);
        addSessionDependency(component, Artifact2FeatureAssociationRepository.class);
        addSessionDependency(component, Feature2DistributionAssociationRepository.class);
        addSessionDependency(component, Distribution2TargetAssociationRepository.class);
        addSessionDependency(component, TargetRepository.class);
        addSessionDependency(component, StatefulTargetRepository.class);
        addDependency(component, ConnectionFactory.class);
    }

    public void start() {
        m_log.log(LogService.LOG_INFO, "Starting session #" + m_sessionID);
        m_dependenciesResolved.set(true);
    }

    @Override
    public void start(URL applicationUrl, Properties applicationProperties, ApplicationContext context) {
        m_component = m_manager.createComponent()
            .setImplementation(this)
            .setCallbacks("setupDependencies", "start", "stop", "destroyDependencies")
            .add(m_manager.createServiceDependency()
                .setService(SessionFactory.class)
                .setRequired(true)
            )
            .add(m_manager.createServiceDependency()
                .setService(UserAdmin.class)
                .setRequired(true)
            )
            .add(m_manager.createServiceDependency()
                .setService(AuthenticationService.class)
                .setRequired(m_useAuth)
            )
            .add(m_manager.createServiceDependency()
                .setService(LogService.class)
                .setRequired(false)
            );
        m_manager.add(m_component);
        super.start(applicationUrl, applicationProperties, context);
    }

    public void stop() throws Exception {
        m_log.log(LogService.LOG_INFO, "Stopping session #" + m_sessionID);

        try {
            close();

            try {
                m_admin.logout(true /* force */);
            }
            catch (IllegalStateException exception) {
                // Ignore, we're already logged out...
            }
        }
        finally {
            m_dependenciesResolved.set(false);
        }
    }

    final void showAddArtifactDialog() {
        final AddArtifactWindow window = new AddArtifactWindow(m_sessionDir, m_obrUrl, m_repositoryXML) {
            @Override
            protected ArtifactRepository getArtifactRepository() {
                return m_artifactRepository;
            }

            @Override
            protected ConnectionFactory getConnectionFactory() {
                return m_connectionFactory;
            }

            @Override
            protected LogService getLogger() {
                return m_log;
            }
        };

        // Open the subwindow by adding it to the parent window
        window.showWindow(getMainWindow());
    }

    final void showManageResourceProcessorsDialog() {
        ManageResourceProcessorWindow window = new ManageResourceProcessorWindow() {
            @Override
            protected ArtifactRepository getArtifactRepository() {
                return m_artifactRepository;
            }
        };
        // Open the subwindow by adding it to the parent window
        window.showWindow(getMainWindow());
    }

    /**
     * Create a new distribution in the distribution repository
     *
     * @param name
     *            the name of the new distribution;
     * @param description
     *            the description of the new distribution.
     */
    protected DistributionObject createDistribution(String name, String description) {
        Map<String, String> attributes = new HashMap<>();
        attributes.put(DistributionObject.KEY_NAME, name);
        attributes.put(DistributionObject.KEY_DESCRIPTION, description);
        Map<String, String> tags = new HashMap<>();
        return m_distributionRepository.create(attributes, tags);
    }

    /**
     * Create a new feature in the feature repository.
     *
     * @param name
     *            the name of the new feature;
     * @param description
     *            the description of the new feature.
     */
    protected FeatureObject createFeature(String name, String description) {
        Map<String, String> attributes = new HashMap<>();
        attributes.put(FeatureObject.KEY_NAME, name);
        attributes.put(FeatureObject.KEY_DESCRIPTION, description);
        Map<String, String> tags = new HashMap<>();
        return m_featureRepository.create(attributes, tags);
    }

    /**
     * Create a new target in the stateful target repository.
     *
     * @param name
     *            the name of the new target;
     */
    protected StatefulTargetObject createTarget(String name) {
        Map<String, String> attributes = new HashMap<>();
        attributes.put(StatefulTargetObject.KEY_ID, name);
        attributes.put(TargetObject.KEY_AUTO_APPROVE, "true");
        Map<String, String> tags = new HashMap<>();
        return m_statefulTargetRepository.preregister(attributes, tags);
    }

    private void addCrossPlatformAddShortcut(Button button, int keycode, String description) {
        // ACE-427 - NPE when using getMainWindow() if no authentication is used...
        WebApplicationContext context = (WebApplicationContext) getContext();
        ShortcutHelper.addCrossPlatformShortcut(context.getBrowser(), button, description, keycode, ModifierKey.SHIFT);
    }

    private void addDependency(Component component, Class<?> service) {
        component.add(m_manager.createServiceDependency()
            .setService(service)
            .setRequired(true)
        );
    }

    private void addListener(final Object implementation, final String... topics) {
        Properties props = new Properties();
        props.put(EventConstants.EVENT_TOPIC, topics);
        props.put(EventConstants.EVENT_FILTER, "(" + SessionFactory.SERVICE_SID + "=" + m_sessionID + ")");
        Component component = m_manager.createComponent()
            .setInterface(EventHandler.class.getName(), props)
            .setImplementation(implementation);
        synchronized (m_eventHandlers) {
            m_eventHandlers.add(component);
        }
        m_manager.add(component);
    }

    private void addSessionDependency(Component component, Class<?> service) {
        component.add(m_manager.createServiceDependency()
            .setService(service, "(" + SessionFactory.SERVICE_SID + "=" + m_sessionID + ")")
            .setRequired(true)
        );
    }

    /**
     * Determines how authentication should take place.
     */
    private void authenticate() {
        if (m_useAuth) {
            showLoginWindow();
        }
        else {
            // Not using authentication; use fallback scenario...
            loginAutomatically();
        }
    }

    private void cleanupListeners() {
        Component[] components;
        synchronized (m_eventHandlers) {
            components = m_eventHandlers.toArray(new Component[m_eventHandlers.size()]);
            m_eventHandlers.clear();
        }
        for (Component component : components) {
            m_manager.remove(component);
        }
    }

    /**
     * Create a button to show a pop window for adding new features.
     *
     * @param user
     *
     * @param main
     *            Main Window
     * @return Button
     */
    private Button createAddArtifactButton() {
        Button button = new Button("+");
        addCrossPlatformAddShortcut(button, KeyCode.A, "Add a new artifact");
        button.addListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                showAddArtifactDialog();
            }
        });
        return button;
    }

    /**
     * Create a button to show a popup window for adding a new distribution. On success this calls the
     * createDistribution() method.
     *
     * @param user
     *
     * @return the add-distribution button instance.
     */
    private Button createAddDistributionButton() {
        Button button = new Button("+");
        addCrossPlatformAddShortcut(button, KeyCode.D, "Add a new distribution");
        button.addListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                GenericAddWindow window = new GenericAddWindow("Add Distribution") {
                    public void handleError(Exception e) {
                        // ACE-241: notify user when the distribution-creation failed!
                        getWindow().showNotification("Failed to add new distribution!",
                            "<br/>Reason: " + e.getMessage(), Notification.TYPE_ERROR_MESSAGE);
                    }

                    public void onOk(String name, String description) {
                        createDistribution(name, description);
                    }
                };
                window.show(getMainWindow());
            }
        });

        return button;
    }

    /***
     * Create a button to show popup window for adding a new feature. On success this calls the createFeature() method.
     *
     * @param user
     *
     * @return the add-feature button instance.
     */
    private Button createAddFeatureButton() {
        Button button = new Button("+");
        addCrossPlatformAddShortcut(button, KeyCode.F, "Add a new feature");
        button.addListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                GenericAddWindow window = new GenericAddWindow("Add Feature") {
                    public void handleError(Exception e) {
                        // ACE-241: notify user when the feature-creation failed!
                        getWindow().showNotification("Failed to add new feature!", "<br/>Reason: " + e.getMessage(),
                            Notification.TYPE_ERROR_MESSAGE);
                    }

                    public void onOk(String name, String description) {
                        createFeature(name, description);
                    }
                };
                window.show(getMainWindow());
            }
        });
        return button;
    }

    /**
     * Create a button to show a popup window for adding a new target. On success this calls the createTarget() method
     *
     * @param user
     *
     * @return the add-target button instance.
     */
    private Button createAddTargetButton() {
        Button button = new Button("+");
        addCrossPlatformAddShortcut(button, KeyCode.G, "Add a new target");
        button.addListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                GenericAddWindow window = new GenericAddWindow("Add Target") {
                    protected void handleError(Exception e) {
                        // ACE-241: notify user when the target-creation failed!
                        getWindow().showNotification("Failed to add new target!", "<br/>Reason: " + e.getMessage(),
                            Notification.TYPE_ERROR_MESSAGE);
                    }

                    @Override
                    protected void initDialog() {
                        m_name.setCaption("Identifier");
                        m_description.setVisible(false);

                        super.initDialog();
                    }

                    protected void onOk(String id, String description) {
                        createTarget(id);
                    }
                };
                window.show(getMainWindow());
            }
        });
        return button;
    }

    /**
     * @return a button to approve one or more targets.
     */
    private Button createApproveTargetsButton() {
        final Button button = new Button("A");
        button.setDisableOnClick(true);
        button.setImmediate(true);
        button.setEnabled(false);
        button.addListener(new Button.ClickListener() {
            @Override
            public void buttonClick(ClickEvent event) {
                m_targetsPanel.approveSelectedTargets();
            }
        });
        m_targetsPanel.addListener(new ValueChangeListener() {
            @Override
            public void valueChange(ValueChangeEvent event) {
                TargetsPanel targetsPanel = (TargetsPanel) event.getProperty();

                Collection<?> itemIDs = (Collection<?>) targetsPanel.getValue();

                boolean enabled = false;
                for (Object itemID : itemIDs) {
                    if (targetsPanel.isItemApproveNeeded(itemID)) {
                        enabled = true;
                        break;
                    }
                }

                button.setEnabled(enabled);
            }
        });
        return button;
    }

    private ArtifactsPanel createArtifactsPanel() {
        return new ArtifactsPanel(m_associations, this, m_cacheRate, m_pageLength) {
            @Override
            protected EditWindow createEditor(final NamedObject object, final List<UIExtensionFactory> extensions) {
                return new EditWindow("Edit Artifact", object, extensions) {
                    @Override
                    protected void handleError(Exception e) {
                        getWindow().showNotification("Failed to edit artifact!", "<br/>Reason: " + e.getMessage(),
                            Notification.TYPE_ERROR_MESSAGE);
                    }

                    @Override
                    protected void onOk(String name, String description) throws Exception {
                        object.setDescription(description);
                    }
                };
            }

            @Override
            protected ArtifactRepository getRepository() {
                return m_artifactRepository;
            }

            @Override
            protected RepositoryAdmin getRepositoryAdmin() {
                return m_admin;
            }
        };
    }

    private HorizontalLayout createArtifactToolbar() {
        HorizontalLayout result = new HorizontalLayout();
        result.setSpacing(true);
        result.addComponent(createAddArtifactButton());
        result.addComponent(createManageResourceProcessorsButton());
        return result;
    }

    private DistributionsPanel createDistributionsPanel() {
        return new DistributionsPanel(m_associations, this) {
            @Override
            protected EditWindow createEditor(final NamedObject object, final List<UIExtensionFactory> extensions) {
                return new EditWindow("Edit Distribution", object, extensions) {
                    @Override
                    protected void handleError(Exception e) {
                        getWindow().showNotification("Failed to edit distribution!", "<br/>Reason: " + e.getMessage(),
                            Notification.TYPE_ERROR_MESSAGE);
                    }

                    @Override
                    protected void onOk(String name, String description) throws Exception {
                        object.setDescription(description);
                    }
                };
            }

            @Override
            protected DistributionRepository getRepository() {
                return m_distributionRepository;
            }

            @Override
            protected RepositoryAdmin getRepositoryAdmin() {
                return m_admin;
            }
        };
    }

    private HorizontalLayout createDistributionToolbar() {
        HorizontalLayout result = new HorizontalLayout();
        result.setSpacing(true);
        result.addComponent(createAddDistributionButton());
        return result;
    }

    private FeaturesPanel createFeaturesPanel() {
        return new FeaturesPanel(m_associations, this) {
            @Override
            protected EditWindow createEditor(final NamedObject object, final List<UIExtensionFactory> extensions) {
                return new EditWindow("Edit Feature", object, extensions) {
                    @Override
                    protected void handleError(Exception e) {
                        getWindow().showNotification("Failed to edit feature!", "<br/>Reason: " + e.getMessage(),
                            Notification.TYPE_ERROR_MESSAGE);
                    }

                    @Override
                    protected void onOk(String name, String description) throws Exception {
                        object.setDescription(description);
                    }
                };
            }

            @Override
            protected FeatureRepository getRepository() {
                return m_featureRepository;
            }

            @Override
            protected RepositoryAdmin getRepositoryAdmin() {
                return m_admin;
            }
        };
    }

    private HorizontalLayout createFeatureToolbar() {
        HorizontalLayout result = new HorizontalLayout();
        result.setSpacing(true);
        result.addComponent(createAddFeatureButton());
        return result;
    }

    private Button createManageResourceProcessorsButton() {
        // Solves ACE-224
        Button button = new Button("RP");
        button.addListener(new Button.ClickListener() {
            @Override
            public void buttonClick(ClickEvent event) {
                showManageResourceProcessorsDialog();
            }
        });
        return button;
    }

    private Button createRegisterTargetsButton() {
        final Button button = new Button("R");
        button.setDisableOnClick(true);
        button.setImmediate(true);
        button.setEnabled(false);
        button.addListener(new Button.ClickListener() {
            @Override
            public void buttonClick(ClickEvent event) {
                m_targetsPanel.registerSelectedTargets();
            }
        });
        m_targetsPanel.addListener(new ValueChangeListener() {
            @Override
            public void valueChange(ValueChangeEvent event) {
                TargetsPanel targetsPanel = (TargetsPanel) event.getProperty();

                Collection<?> itemIDs = (Collection<?>) targetsPanel.getValue();

                boolean enabled = false;
                for (Object itemID : itemIDs) {
                    if (targetsPanel.isItemRegistrationNeeded(itemID)) {
                        enabled = true;
                        break;
                    }
                }

                button.setEnabled(enabled);
            }
        });
        return button;
    }

    private TargetsPanel createTargetsPanel() {
        return new TargetsPanel(m_associations, this) {
            @Override
            protected EditWindow createEditor(final NamedObject object, final List<UIExtensionFactory> extensions) {
                return new EditWindow("Edit Target", object, extensions) {
                    @Override
                    protected void handleError(Exception e) {
                        getWindow().showNotification("Failed to edit target!", "<br/>Reason: " + e.getMessage(),
                            Notification.TYPE_ERROR_MESSAGE);
                    }

                    @Override
                    protected void initDialog(NamedObject object, List<UIExtensionFactory> factories) {
                        m_name.setCaption("Identifier");
                        m_name.setReadOnly(true);
                        m_description.setVisible(false);

                        super.initDialog(object, factories);
                    }

                    @Override
                    protected void onOk(String name, String description) throws Exception {
                        // Nothing to edit!
                    }

                    @Override
                    protected Map<String, Object> populateContext(Map<String, Object> context) {
                        if (object instanceof NamedTargetObject) {
                            context.put("statefulTarget", m_statefulTargetRepository.get(object.getDefinition()));
                        }
                        else if (object instanceof NamedStatefulTargetObject) {
                            context.put("statefulTarget", object.getObject());
                        }
                        return context;
                    }
                };
            }

            @Override
            protected TargetRepository getRepository() {
                return m_targetRepository;
            }

            @Override
            protected RepositoryAdmin getRepositoryAdmin() {
                return m_admin;
            }

            @Override
            protected StatefulTargetRepository getStatefulTargetRepository() {
                return m_statefulTargetRepository;
            }
        };
    }

    private HorizontalLayout createTargetToolbar() {
        HorizontalLayout result = new HorizontalLayout();
        result.setSpacing(true);
        result.addComponent(createAddTargetButton());
        result.addComponent(createRegisterTargetsButton());
        result.addComponent(createApproveTargetsButton());
        return result;
    }

    private GridLayout createToolbar() {
        return new MainActionToolbar(m_useAuth) {
            @Override
            protected void doAfterCommit() throws IOException {
                updateTableData();

                m_statusLine.setStatus("Local changes committed...");
            }

            @Override
            protected void doAfterLogout() throws IOException {
                // Close the application and reload the main window...
                close();
            }

            @Override
            protected void doAfterRetrieve() throws IOException {
                updateTableData();

                m_statusLine.setStatus("Repositories updated...");
            }

            @Override
            protected void doAfterRevert() throws IOException {
                updateTableData();

                m_statusLine.setStatus("Local changes reverted...");
            }

            @Override
            protected RepositoryAdmin getRepositoryAdmin() {
                return m_admin;
            }

            @Override
            protected void log(int level, String msg, Exception e, Object... args) {
                m_log.log(level, String.format(msg, args), e);
            }

            private void updateTableData() {
                m_artifactsPanel.populate();
                m_featuresPanel.populate();
                m_distributionsPanel.populate();
                m_targetsPanel.populate();

                m_mainWindow.focus();
            }
        };
    }

    /**
     * Authenticates the given user by creating all dependent services.
     *
     * @param user
     * @throws IOException
     *             in case of I/O problems.
     */
    private boolean doLogin() {
        try {
            RepositoryAdminLoginContext context = m_admin.createLoginContext((User) getUser());

            // @formatter:off
            context
                .add(context.createShopRepositoryContext()
                    .setLocation(m_repository).setCustomer(customerName).setName(shopRepo).setWriteable())
                .add(context.createTargetRepositoryContext()
                    .setLocation(m_repository).setCustomer(customerName).setName(targetRepo).setWriteable())
                .add(context.createDeploymentRepositoryContext()
                    .setLocation(m_repository).setCustomer(customerName).setName(deployRepo).setWriteable());
            // @formatter:on

            m_admin.login(context);
            m_admin.checkout();

            initGrid();

            return true;
        }
        catch (Exception e) {
            m_log.log(LogService.LOG_WARNING, "Login failed! Destroying session...", e);

            try {
                // Avoid errors when the user tries to login again (due to the stale session)...
                m_admin.logout(true /* force */);
            }
            catch (IllegalStateException inner) {
                // Ignore; probably we're not logged...
            }
            catch (IOException inner) {
                m_log.log(LogService.LOG_WARNING, "Logout failed! Session possibly not destroyed...", inner);
            }

            return false;
        }
    }

    private void initGrid() {
        User user = (User) getUser();
        Authorization auth = m_userAdmin.getAuthorization(user);
        int count = 0;
        for (String role : new String[] { "viewArtifact", "viewFeature", "viewDistribution", "viewTarget" }) {
            if (auth.hasRole(role)) {
                count++;
            }
        }

        final GenericUploadHandler uploadHandler = new GenericUploadHandler(m_sessionDir) {
            @Override
            public void updateProgress(long readBytes, long contentLength) {
                Float percentage = new Float(readBytes / (float) contentLength);
                m_progress.setValue(percentage);
            }

            @Override
            protected void artifactsUploaded(List<UploadHandle> uploadedArtifacts) {
                StringBuilder failedMsg = new StringBuilder();
                StringBuilder successMsg = new StringBuilder();
                Set<String> selection = new HashSet<>();

                for (UploadHandle handle : uploadedArtifacts) {
                    if (!handle.isSuccessful()) {
                        // Upload failed, so let's report this one...
                        appendFailure(failedMsg, handle);

                        m_log.log(LogService.LOG_ERROR, "Upload of " + handle.getFile() + " failed.", handle.getFailureReason());
                    }
                    else {
                        try {
                            // Upload was successful, try to upload it to our OBR...
                            ArtifactObject artifact = uploadToOBR(handle);
                            if (artifact != null) {
                                selection.add(artifact.getDefinition());

                                appendSuccess(successMsg, handle);
                            }
                        }
                        catch (ArtifactAlreadyExistsException exception) {
                            appendFailureExists(failedMsg, handle);

                            m_log.log(LogService.LOG_WARNING, "Upload of " + handle.getFilename() + " failed, as it already exists!");
                        }
                        catch (Exception exception) {
                            appendFailure(failedMsg, handle, exception);

                            m_log.log(LogService.LOG_ERROR, "Upload of " + handle.getFilename() + " failed.", exception);
                        }
                    }

                    // We're done with this (temporary) file, so we can remove it...
                    handle.cleanup();
                }

                m_artifactsPanel.setValue(selection);

                // Notify the user what the overall status was...
                Notification notification = createNotification(failedMsg, successMsg);
                getMainWindow().showNotification(notification);

                m_progress.setStyleName("invisible");
                m_statusLine.setStatus(notification.getCaption() + "...");
            }

            @Override
            protected void uploadStarted(UploadHandle upload) {
                m_progress.setStyleName("visible");
                m_progress.setValue(new Float(0.0f));

                m_statusLine.setStatus("Upload of '%s' started...", upload.getFilename());
            }

            private void appendFailure(StringBuilder sb, UploadHandle handle) {
                appendFailure(sb, handle, handle.getFailureReason());
            }

            private void appendFailure(StringBuilder sb, UploadHandle handle, Exception cause) {
                sb.append("<li>'").append(handle.getFile().getName()).append("': failed");
                if (cause != null) {
                    sb.append(", possible reason:<br/>").append(cause.getMessage());
                }
                sb.append("</li>");
            }

            private void appendFailureExists(StringBuilder sb, UploadHandle handle) {
                sb.append("<li>'").append(handle.getFile().getName()).append("': already exists in repository</li>");
            }

            private void appendSuccess(StringBuilder sb, UploadHandle handle) {
                sb.append("<li>'").append(handle.getFile().getName()).append("': added to repository</li>");
            }

            private Notification createNotification(StringBuilder failedMsg, StringBuilder successMsg) {
                String caption = "Upload completed";
                int delay = 500; // msec.
                StringBuilder notification = new StringBuilder();
                if (failedMsg.length() > 0) {
                    caption = "Upload completed with failures";
                    delay = -1;
                    notification.append("<ul>").append(failedMsg).append("</ul>");
                }
                if (successMsg.length() > 0) {
                    notification.append("<ul>").append(successMsg).append("</ul>");
                }
                if (delay < 0) {
                    notification.append("<p>(click to dismiss this notification).</p>");
                }

                Notification summary = new Notification(caption, notification.toString(), Notification.TYPE_TRAY_NOTIFICATION);
                summary.setDelayMsec(delay);
                return summary;
            }

            private ArtifactObject uploadToOBR(UploadHandle handle) throws IOException {
                return UploadHelper.importRemoteBundle(m_artifactRepository, handle.getFile());
            }
        };

        m_grid = new GridLayout(count, 4);
        m_grid.setSpacing(true);
        m_grid.setSizeFull();

        m_mainToolbar = createToolbar();
        m_grid.addComponent(m_mainToolbar, 0, 0, count - 1, 0);

        m_artifactsPanel = createArtifactsPanel();
        m_artifactToolbar = createArtifactToolbar();

        final DragAndDropWrapper artifactsPanelWrapper = new DragAndDropWrapper(m_artifactsPanel);
        artifactsPanelWrapper.setDragStartMode(DragStartMode.HTML5);
        artifactsPanelWrapper.setDropHandler(new ArtifactDropHandler(uploadHandler));
        artifactsPanelWrapper.setCaption(m_artifactsPanel.getCaption());
        artifactsPanelWrapper.setSizeFull();

        count = 0;
        if (auth.hasRole("viewArtifact")) {
            m_grid.addComponent(artifactsPanelWrapper, count, 2);
            m_grid.addComponent(m_artifactToolbar, count, 1);
            count++;
        }

        m_featuresPanel = createFeaturesPanel();
        m_featureToolbar = createFeatureToolbar();

        if (auth.hasRole("viewFeature")) {
            m_grid.addComponent(m_featuresPanel, count, 2);
            m_grid.addComponent(m_featureToolbar, count, 1);
            count++;
        }

        m_distributionsPanel = createDistributionsPanel();
        m_distributionToolbar = createDistributionToolbar();

        if (auth.hasRole("viewDistribution")) {
            m_grid.addComponent(m_distributionsPanel, count, 2);
            m_grid.addComponent(m_distributionToolbar, count, 1);
            count++;
        }

        m_targetsPanel = createTargetsPanel();
        m_targetToolbar = createTargetToolbar();

        if (auth.hasRole("viewTarget")) {
            m_grid.addComponent(m_targetsPanel, count, 2);
            m_grid.addComponent(m_targetToolbar, count, 1);
        }

        m_statusLine = new StatusLine();

        m_grid.addComponent(m_statusLine, 0, 3, 2, 3);

        m_progress = new ProgressIndicator(0f);
        m_progress.setStyleName("invisible");
        m_progress.setIndeterminate(false);
        m_progress.setPollingInterval(1000);

        m_grid.addComponent(m_progress, 3, 3);

        m_grid.setRowExpandRatio(2, 1.0f);

        m_grid.setColumnExpandRatio(0, 0.31f);
        m_grid.setColumnExpandRatio(1, 0.23f);
        m_grid.setColumnExpandRatio(2, 0.23f);
        m_grid.setColumnExpandRatio(3, 0.23f);

        // Wire up all panels so they have the correct associations...
        m_artifactsPanel.setAssociatedTables(null, m_featuresPanel);
        m_featuresPanel.setAssociatedTables(m_artifactsPanel, m_distributionsPanel);
        m_distributionsPanel.setAssociatedTables(m_featuresPanel, m_targetsPanel);
        m_targetsPanel.setAssociatedTables(m_distributionsPanel, null);

        addListener(m_statusLine, StatefulTargetObject.TOPIC_ALL, RepositoryObject.PUBLIC_TOPIC_ROOT.concat(RepositoryObject.TOPIC_ALL_SUFFIX));
        addListener(m_mainToolbar, StatefulTargetObject.TOPIC_ALL, RepositoryAdmin.TOPIC_STATUSCHANGED, RepositoryAdmin.TOPIC_LOGIN, RepositoryAdmin.TOPIC_REFRESH);
        addListener(m_artifactsPanel, ArtifactObject.TOPIC_ALL, RepositoryAdmin.TOPIC_STATUSCHANGED, RepositoryAdmin.TOPIC_LOGIN, RepositoryAdmin.TOPIC_REFRESH);
        addListener(m_featuresPanel, FeatureObject.TOPIC_ALL, RepositoryAdmin.TOPIC_STATUSCHANGED, RepositoryAdmin.TOPIC_LOGIN, RepositoryAdmin.TOPIC_REFRESH);
        addListener(m_distributionsPanel, DistributionObject.TOPIC_ALL, RepositoryAdmin.TOPIC_STATUSCHANGED, RepositoryAdmin.TOPIC_LOGIN, RepositoryAdmin.TOPIC_REFRESH);
        addListener(m_targetsPanel, StatefulTargetObject.TOPIC_ALL, TargetObject.TOPIC_ALL, RepositoryAdmin.TOPIC_STATUSCHANGED, RepositoryAdmin.TOPIC_LOGIN, RepositoryAdmin.TOPIC_REFRESH);

        m_mainWindow.addComponent(m_grid);
        // Ensure the focus is properly defined (for the shortcut keys to work)...
        m_mainWindow.focus();
    }

    /**
     * @return <code>true</code> if the login succeeded, <code>false</code> otherwise.
     */
    private boolean loginAutomatically() {
        setUser(m_userAdmin.getUser("username", m_userName));
        return doLogin();
    }

    /**
     * Shows the login window on the center of the main window.
     */
    private void showLoginWindow() {
        LoginWindow loginWindow = new LoginWindow(m_log, this);

        loginWindow.openWindow(getMainWindow());
    }
}
