package org.bndtools.core.resolve.ui;

import java.util.List;
import java.util.Map.Entry;

import org.bndtools.core.ui.resource.R5LabelFormatter;
import org.bndtools.utils.jface.BoldStyler;
import org.bndtools.utils.jface.ItalicStyler;
import org.bndtools.utils.resources.ResourceUtils;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.osgi.resource.Capability;
import org.osgi.resource.Namespace;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;

import bndtools.model.resolution.CapabilityLabelProvider;

public class ResolutionChoiceSelectionDialog extends TitleAreaDialog {

    private final Requirement requirement;
    private final List<Capability> candidates;

    private CheckboxTableViewer viewer;
    private Button btnUp;
    private Button btnDown;

    private Button btnSavePreference;
    private StyledText txtSavePreference;

    public ResolutionChoiceSelectionDialog(Shell shell, Requirement requirement, List<Capability> candidates) {
        super(shell);
        this.requirement = requirement;
        this.candidates = candidates;
    }

    @SuppressWarnings("unused")
    @Override
    protected Control createDialogArea(Composite parent) {
        setTitle("Multiple Provider Candidates");
        setMessage("Use the candidate list to specify your preferences. Candidates at the top of the list will be preferred by the resolver.");

        // Create controls
        Composite outer = (Composite) super.createDialogArea(parent);
        Composite contents = new Composite(outer, SWT.NONE);

        Label lblRequirement = new Label(contents, SWT.NONE);
        lblRequirement.setText("Requirement Info");
        lblRequirement.setFont(JFaceResources.getFontRegistry()
            .getBold(JFaceResources.DIALOG_FONT));

        StyledText txtRequirement = new StyledText(contents, SWT.WRAP | SWT.BORDER);
        txtRequirement.setEditable(false);
        txtRequirement.setCaret(null);
        // txtRequirement.setBackground(contents.getBackground());
        txtRequirement.setCursor(parent.getDisplay()
            .getSystemCursor(SWT.CURSOR_ARROW));

        new Label(contents, SWT.NONE);

        Label lblCandidates = new Label(contents, SWT.NONE);
        lblCandidates.setText("Candidates");
        lblCandidates.setFont(JFaceResources.getFontRegistry()
            .getBold(JFaceResources.DIALOG_FONT));

        Composite lowerPanel = new Composite(contents, SWT.NONE);
        Table tbl = new Table(lowerPanel, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER);

        viewer = new CheckboxTableViewer(tbl);
        viewer.setContentProvider(ArrayContentProvider.getInstance());
        viewer.setLabelProvider(new CapabilityLabelProvider());

        btnUp = new Button(lowerPanel, SWT.PUSH);
        btnUp.setText("Move Up");
        btnUp.setEnabled(false);

        btnDown = new Button(lowerPanel, SWT.PUSH);
        btnDown.setText("Move Down");
        btnDown.setEnabled(false);

        Composite cmpPreferences = new Composite(contents, SWT.NONE);
        btnSavePreference = new Button(cmpPreferences, SWT.CHECK | SWT.WRAP);
        txtSavePreference = new StyledText(cmpPreferences, SWT.WRAP);
        txtSavePreference.setEditable(false);
        txtSavePreference.setCaret(null);
        txtSavePreference.setBackground(contents.getBackground());
        txtSavePreference.setCursor(parent.getDisplay()
            .getSystemCursor(SWT.CURSOR_ARROW));

        // Events
        txtSavePreference.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseDown(MouseEvent e) {
                btnSavePreference.setSelection(!btnSavePreference.getSelection());
            }
        });

        // Load data
        StyledString label = createRequirementText();
        txtRequirement.setText(label.getString());
        txtRequirement.setStyleRanges(label.getStyleRanges());

        viewer.setInput(candidates);

        updateSavePreferenceText();

        // Layout
        GridLayout layout;
        GridData gd;

        gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        contents.setLayoutData(gd);
        layout = new GridLayout(1, false);
        contents.setLayout(layout);

        gd = new GridData(SWT.FILL, SWT.NONE, true, false);
        gd.horizontalIndent = 5;
        txtRequirement.setLayoutData(gd);
        gd = new GridData(SWT.FILL, SWT.NONE, true, false);

        gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        lowerPanel.setLayoutData(gd);

        layout = new GridLayout(2, false);
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        lowerPanel.setLayout(layout);

        gd = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 3);
        gd.widthHint = 450;
        gd.heightHint = 250;
        tbl.setLayoutData(gd);

        gd = new GridData(SWT.FILL, SWT.NONE, false, false);
        btnUp.setLayoutData(gd);
        gd = new GridData(SWT.FILL, SWT.NONE, false, false);
        btnDown.setLayoutData(gd);

        gd = new GridData(SWT.FILL, SWT.NONE, true, false);
        cmpPreferences.setLayoutData(gd);

        layout = new GridLayout(2, false);
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        cmpPreferences.setLayout(layout);

        gd = new GridData(SWT.LEFT, SWT.CENTER, false, false);
        btnSavePreference.setLayoutData(gd);
        gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
        txtSavePreference.setLayoutData(gd);

        return contents;
    }

    private void updateSavePreferenceText() {
        Resource resource = candidates.get(0)
            .getResource();
        Capability identity = ResourceUtils.getIdentityCapability(resource);
        String name = ResourceUtils.getIdentity(identity);

        StyledString label = new StyledString("Save top candidate (");
        label.append(name, BoldStyler.INSTANCE_DEFAULT);
        label.append(") as a ");
        label.append("preferred resource.", ItalicStyler.INSTANCE_DEFAULT);

        txtSavePreference.setText(label.getString());
        txtSavePreference.setStyleRanges(label.getStyleRanges());
    }

    protected StyledString createRequirementText() {
        StyledString label = new StyledString();
        label.append("Namespace: ");
        label.append(requirement.getNamespace() + "\n", BoldStyler.INSTANCE_DEFAULT);

        label.append("Filter: ");
        R5LabelFormatter.appendRequirementLabel(label, requirement, false);
        label.append("\n");

        for (Entry<String, String> entry : requirement.getDirectives()
            .entrySet()) {
            String key = entry.getKey();
            if (!Namespace.REQUIREMENT_FILTER_DIRECTIVE.equals(key) && !Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE.equals(key))
                label.append("    " + key + ":=" + entry.getValue() + "\n");
        }

        if (Namespace.RESOLUTION_OPTIONAL.equals(requirement.getDirectives()
            .get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE)))
            label.append("Optionally ", ItalicStyler.INSTANCE_DEFAULT);
        label.append("Required by Resource: ");
        R5LabelFormatter.appendResourceLabel(label, requirement.getResource());

        return label;
    }

    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.NEXT_LABEL, true);
        createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
    }

}
