/*
 * Copyright (C) 2011 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.layout.refactoring;

import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ATTR_LAYOUT_HEIGHT;
import static com.android.SdkConstants.ATTR_LAYOUT_WIDTH;
import static com.android.SdkConstants.EXT_XML;

import com.android.annotations.NonNull;
import com.android.annotations.VisibleForTesting;
import com.android.ide.common.xml.XmlFormatStyle;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Removes the layout surrounding the current selection (or if the current selection has
 * children, removes the current layout), and migrates namespace and layout attributes.
 */
@SuppressWarnings("restriction") // XML model
public class UnwrapRefactoring extends VisualRefactoring {
    private Element mContainer;

    /**
     * This constructor is solely used by {@link Descriptor},
     * to replay a previous refactoring.
     * @param arguments argument map created by #createArgumentMap.
     */
    UnwrapRefactoring(Map<String, String> arguments) {
        super(arguments);
    }

    public UnwrapRefactoring(
            IFile file,
            LayoutEditorDelegate delegate,
            ITextSelection selection,
            ITreeSelection treeSelection) {
        super(file, delegate, selection, treeSelection);
    }

    @VisibleForTesting
    UnwrapRefactoring(List<Element> selectedElements, LayoutEditorDelegate editor) {
        super(selectedElements, editor);
    }

    @Override
    public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException,
            OperationCanceledException {
        RefactoringStatus status = new RefactoringStatus();

        try {
            pm.beginTask("Checking preconditions...", 6);

            if (mSelectionStart == -1 || mSelectionEnd == -1) {
                status.addFatalError("No selection to wrap");
                return status;
            }

            // Make sure that the selection all has the same parent?
            if (mElements.size() == 0) {
                status.addFatalError("Nothing to unwrap");
                return status;
            }

            Element first = mElements.get(0);

            // Determine the element of the container to be removed.
            // If you've selected a non-container, or you've selected multiple
            // elements, then it's the parent which should be removed. Otherwise,
            // it's the selection itself which represents the container.
            boolean useParent = mElements.size() > 1;
            if (!useParent) {
                if (DomUtilities.getChildren(first).size() == 0) {
                    useParent = true;
                }
            }
            Node parent = first.getParentNode();
            if (parent instanceof Document) {
                mContainer = first;
                List<Element> elements = DomUtilities.getChildren(mContainer);
                if (elements.size() == 0) {
                    status.addFatalError(
                            "Cannot remove container when it has no children");
                        return status;
                }
            } else if (useParent && (parent instanceof Element)) {
                mContainer = (Element) parent;
            } else {
                mContainer = first;
            }

            for (Element element : mElements) {
                if (element.getParentNode() != parent) {
                    status.addFatalError(
                            "All unwrapped elements must share the same parent element");
                    return status;
                }
            }

            // Ensure that if we are removing the root, that it has only one child
            // such that there is a new single root
            if (mContainer.getParentNode() instanceof Document) {
                if (DomUtilities.getChildren(mContainer).size() > 1) {
                    status.addFatalError(
                        "Cannot remove root: it has more than one child "
                            + "which would result in multiple new roots");
                    return status;
                }
            }

            pm.worked(1);
            return status;

        } finally {
            pm.done();
        }
    }

    @Override
    protected VisualRefactoringDescriptor createDescriptor() {
        String comment = getName();
        return new Descriptor(
                mProject.getName(), //project
                comment, //description
                comment, //comment
                createArgumentMap());
    }

    @Override
    public String getName() {
        return "Remove Container";
    }

    @Override
    protected @NonNull List<Change> computeChanges(IProgressMonitor monitor) {
        // (1) If the removed parent is the root container, transfer its
        //   namespace declarations
        // (2) Remove the root element completely
        // (3) Transfer layout attributes?
        // (4) Check for Java R.file usages?

        IFile file = mDelegate.getEditor().getInputFile();
        List<Change> changes = new ArrayList<Change>();
        if (file == null) {
            return changes;
        }
        MultiTextEdit rootEdit = new MultiTextEdit();

        // Transfer namespace elements?
        if (mContainer.getParentNode() instanceof Document) {
            List<Element> elements = DomUtilities.getChildren(mContainer);
            assert elements.size() == 1;
            Element newRoot = elements.get(0);

            List<Attr> declarations = findNamespaceAttributes(mContainer);
            for (Attr attribute : declarations) {
                if (attribute instanceof IndexedRegion) {
                    setAttribute(rootEdit, newRoot, attribute.getNamespaceURI(),
                            attribute.getPrefix(), attribute.getLocalName(), attribute.getValue());
                }
            }
        }

        // Transfer layout_ attributes (other than width and height)
         List<Element> children = DomUtilities.getChildren(mContainer);
         if (children.size() == 1) {
            List<Attr> layoutAttributes = findLayoutAttributes(mContainer);
            for (Attr attribute : layoutAttributes) {
                String name = attribute.getLocalName();
                if ((name.equals(ATTR_LAYOUT_WIDTH) || name.equals(ATTR_LAYOUT_HEIGHT))
                        && ANDROID_URI.equals(attribute.getNamespaceURI())) {
                    // Already handled specially
                    continue;
                }
            }
        }

         // Remove the root
         removeElementTags(rootEdit, mContainer, Collections.<Element>emptyList() /* skip */,
                 false /*changeIndentation*/);

         MultiTextEdit formatted = reformat(rootEdit, XmlFormatStyle.LAYOUT);
         if (formatted != null) {
             rootEdit = formatted;
         }

         TextFileChange change = new TextFileChange(file.getName(), file);
         change.setEdit(rootEdit);
         change.setTextType(EXT_XML);
         changes.add(change);
         return changes;
    }

    @Override
    public VisualRefactoringWizard createWizard() {
        return new UnwrapWizard(this, mDelegate);
    }

    public static class Descriptor extends VisualRefactoringDescriptor {
        public Descriptor(String project, String description, String comment,
                Map<String, String> arguments) {
            super("com.android.ide.eclipse.adt.refactoring.unwrap", //$NON-NLS-1$
                    project, description, comment, arguments);
        }

        @Override
        protected Refactoring createRefactoring(Map<String, String> args) {
            return new UnwrapRefactoring(args);
        }
    }
}
