/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
 *
 * 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 com.android.ide.eclipse.adt.internal.editors.manifest.pages;

import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestEditor;
import com.android.ide.eclipse.adt.internal.editors.ui.UiElementPart;
import com.android.ide.eclipse.adt.internal.editors.uimodel.IUiUpdateListener;
import com.android.ide.eclipse.adt.internal.editors.uimodel.IUiUpdateListener.UiUpdateState;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.utils.SdkUtils;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.widgets.FormText;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.forms.widgets.TableWrapData;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

/**
 * Appllication Toogle section part for application page.
 */
final class ApplicationToggle extends UiElementPart {

    /** Checkbox indicating whether an application node is present */
    private Button mCheckbox;
    /** Listen to changes to the UI node for <application> and updates the checkbox */
    private AppNodeUpdateListener mAppNodeUpdateListener;
    /** Internal flag to know where we're programmatically modifying the checkbox and we want to
     *  avoid triggering the checkbox's callback. */
    public boolean mInternalModification;
    private FormText mTooltipFormText;

    public ApplicationToggle(Composite body, FormToolkit toolkit, ManifestEditor editor,
            UiElementNode applicationUiNode) {
        super(body, toolkit, editor, applicationUiNode,
                "Application Toggle",
                null, /* description */
                Section.TWISTIE | Section.EXPANDED);
    }

    @Override
    public void dispose() {
        super.dispose();
        if (getUiElementNode() != null && mAppNodeUpdateListener != null) {
            getUiElementNode().removeUpdateListener(mAppNodeUpdateListener);
            mAppNodeUpdateListener = null;
        }
    }

    /**
     * Changes and refreshes the Application UI node handle by the this part.
     */
    @Override
    public void setUiElementNode(UiElementNode uiElementNode) {
        super.setUiElementNode(uiElementNode);

        updateTooltip();

        // Set the state of the checkbox
        mAppNodeUpdateListener.uiElementNodeUpdated(getUiElementNode(),
                UiUpdateState.CHILDREN_CHANGED);
    }

    /**
     * Create the controls to edit the attributes for the given ElementDescriptor.
     * <p/>
     * This MUST not be called by the constructor. Instead it must be called from
     * <code>initialize</code> (i.e. right after the form part is added to the managed form.)
     *
     * @param managedForm The owner managed form
     */
    @Override
    protected void createFormControls(IManagedForm managedForm) {
        FormToolkit toolkit = managedForm.getToolkit();
        Composite table = createTableLayout(toolkit, 1 /* numColumns */);

        mTooltipFormText = createFormText(table, toolkit, true, "<form></form>",
                false /* setupLayoutData */);
        updateTooltip();

        mCheckbox = toolkit.createButton(table,
                "Define an <application> tag in the AndroidManifest.xml",
                SWT.CHECK);
        mCheckbox.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.TOP));
        mCheckbox.setSelection(false);
        mCheckbox.addSelectionListener(new CheckboxSelectionListener());

        mAppNodeUpdateListener = new AppNodeUpdateListener();
        getUiElementNode().addUpdateListener(mAppNodeUpdateListener);

        // Initialize the state of the checkbox
        mAppNodeUpdateListener.uiElementNodeUpdated(getUiElementNode(),
                UiUpdateState.CHILDREN_CHANGED);

        // Tell the section that the layout has changed.
        layoutChanged();
    }

    /**
     * Updates the application tooltip in the form text.
     * If there is no tooltip, the form text is hidden.
     */
    private void updateTooltip() {
        boolean isVisible = false;

        String tooltip = getUiElementNode().getDescriptor().getTooltip();
        if (tooltip != null) {
            tooltip = DescriptorsUtils.formatFormText(tooltip,
                    getUiElementNode().getDescriptor(),
                    Sdk.getCurrent().getDocumentationBaseUrl());

            mTooltipFormText.setText(tooltip, true /* parseTags */, true /* expandURLs */);
            mTooltipFormText.setImage(DescriptorsUtils.IMAGE_KEY, AdtPlugin.getAndroidLogo());
            mTooltipFormText.addHyperlinkListener(getEditor().createHyperlinkListener());
            isVisible = true;
        }

        mTooltipFormText.setVisible(isVisible);
    }

    /**
     * This listener synchronizes the XML application node when the checkbox
     * is changed by the user.
     */
    private class CheckboxSelectionListener extends SelectionAdapter {
        private Node mUndoXmlNode;
        private Node mUndoXmlParent;
        private Node mUndoXmlNextNode;
        private Node mUndoXmlNextElement;
        private Document mUndoXmlDocument;

        @Override
        public void widgetSelected(SelectionEvent e) {
            super.widgetSelected(e);
            if (!mInternalModification && getUiElementNode() != null) {
                getUiElementNode().getEditor().wrapUndoEditXmlModel(
                        mCheckbox.getSelection()
                            ? "Create or restore Application node"
                            : "Remove Application node",
                        new Runnable() {
                            @Override
                            public void run() {
                                if (mCheckbox.getSelection()) {
                                    // The user wants an <application> node.
                                    // Either restore a previous one
                                    // or create a full new one.
                                    boolean create = true;
                                    if (mUndoXmlNode != null) {
                                        create = !restoreApplicationNode();
                                    }
                                    if (create) {
                                        getUiElementNode().createXmlNode();
                                    }
                                } else {
                                    // Users no longer wants the <application> node.
                                    removeApplicationNode();
                                }
                            }
                });
            }
        }

        /**
         * Restore a previously "saved" application node.
         *
         * @return True if the node could be restored, false otherwise.
         */
        private boolean restoreApplicationNode() {
            if (mUndoXmlDocument == null || mUndoXmlNode == null) {
                return false;
            }

            // Validate node references...
            mUndoXmlParent = validateNode(mUndoXmlDocument, mUndoXmlParent);
            mUndoXmlNextNode = validateNode(mUndoXmlDocument, mUndoXmlNextNode);
            mUndoXmlNextElement = validateNode(mUndoXmlDocument, mUndoXmlNextElement);

            if (mUndoXmlParent == null){
                // If the parent node doesn't exist, try to find a new manifest node.
                // If it doesn't exist, create it.
                mUndoXmlParent = getUiElementNode().getUiParent().prepareCommit();
                mUndoXmlNextNode = null;
                mUndoXmlNextElement = null;
            }

            boolean success = false;
            if (mUndoXmlParent != null) {
                // If the parent is still around, reuse the same node.

                // Ideally we want to insert the node before what used to be its next sibling.
                // If that's not possible, we try to insert it before its next sibling element.
                // If that's not possible either, it will be inserted at the end of the parent's.
                Node next = mUndoXmlNextNode;
                if (next == null) {
                    next = mUndoXmlNextElement;
                }
                mUndoXmlParent.insertBefore(mUndoXmlNode, next);
                if (next == null) {
                    Text sep = mUndoXmlDocument.createTextNode(SdkUtils.getLineSeparator());
                    mUndoXmlParent.insertBefore(sep, null);  // insert separator before end tag
                }
                success = true;
            }

            // Remove internal references to avoid using them twice
            mUndoXmlParent = null;
            mUndoXmlNextNode = null;
            mUndoXmlNextElement = null;
            mUndoXmlNode = null;
            mUndoXmlDocument = null;
            return success;
        }

        /**
         * Validates that the given xml_node is still either the root node or one of its
         * direct descendants.
         *
         * @param root_node The root of the node hierarchy to examine.
         * @param xml_node The XML node to find.
         * @return Returns xml_node if it is, otherwise returns null.
         */
        private Node validateNode(Node root_node, Node xml_node) {
            if (root_node == xml_node) {
                return xml_node;
            } else {
                for (Node node = root_node.getFirstChild(); node != null;
                        node = node.getNextSibling()) {
                    if (root_node == xml_node || validateNode(node, xml_node) != null) {
                        return xml_node;
                    }
                }
            }
            return null;
        }

        /**
         * Removes the <application> node from the hierarchy.
         * Before doing that, we try to remember where it was so that we can put it back
         * in the same place.
         */
        private void removeApplicationNode() {
            // Make sure the node actually exists...
            Node xml_node = getUiElementNode().getXmlNode();
            if (xml_node == null) {
                return;
            }

            // Save its parent, next sibling and next element
            mUndoXmlDocument = xml_node.getOwnerDocument();
            mUndoXmlParent = xml_node.getParentNode();
            mUndoXmlNextNode = xml_node.getNextSibling();
            mUndoXmlNextElement = mUndoXmlNextNode;
            while (mUndoXmlNextElement != null &&
                    mUndoXmlNextElement.getNodeType() != Node.ELEMENT_NODE) {
                mUndoXmlNextElement = mUndoXmlNextElement.getNextSibling();
            }

            // Actually remove the node from the hierarchy and keep it here.
            // The returned node looses its parents/siblings pointers.
            mUndoXmlNode = getUiElementNode().deleteXmlNode();
        }
    }

    /**
     * This listener synchronizes the UI (i.e. the checkbox) with the
     * actual presence of the application XML node.
     */
    private class AppNodeUpdateListener implements IUiUpdateListener {
        @Override
        public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) {
            // The UiElementNode for the application XML node always exists, even
            // if there is no corresponding XML node in the XML file.
            //
            // To update the checkbox to reflect the actual state, we just need
            // to check if the XML node is null.
            try {
                mInternalModification = true;
                boolean exists = ui_node.getXmlNode() != null;
                if (mCheckbox.getSelection() != exists) {
                    mCheckbox.setSelection(exists);
                }
            } finally {
                mInternalModification = false;
            }

        }
    }
}
