/*
 * 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_WIDGET_PREFIX;
import static com.android.SdkConstants.DOT_XML;

import com.android.ide.common.rendering.api.ViewInfo;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.w3c.dom.Element;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@SuppressWarnings("restriction")
public class RefactoringTest extends AdtProjectTest {

    protected boolean autoFormat() {
        return true;
    }

    @Override
    protected void setUp() throws Exception {

        // Ensure that the defaults are initialized so for example formatting options are
        // initialized properly
        IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore();
        AdtPrefs.init(store);
        AdtPrefs prefs = AdtPrefs.getPrefs();
        prefs.initializeStoreWithDefaults(store);

        store.setValue(AdtPrefs.PREFS_FORMAT_GUI_XML, autoFormat());

        prefs.loadValues(null);

        super.setUp();
    }

    protected static Element findElementById(Element root, String id) {
        if (id.equals(VisualRefactoring.getId(root))) {
            return root;
        }

        for (Element child : DomUtilities.getChildren(root)) {
            Element result = findElementById(child, id);
            if (result != null) {
                return result;
            }
        }

        return null;
    }

    protected static List<Element> getElements(Element root, String... ids) {
        List<Element> selectedElements = new ArrayList<Element>();
        for (String id : ids) {
            Element element = findElementById(root, id);
            assertNotNull(element);
            selectedElements.add(element);
        }
        return selectedElements;
    }

    protected void checkEdits(String basename, List<Change> changes) throws BadLocationException,
            IOException {
        IDocument document = new Document();

        String xml = readTestFile(basename, false);
        if (xml == null) { // New file
            xml = ""; //$NON-NLS-1$
        }
        document.set(xml);

        for (Change change : changes) {
            if (change instanceof TextFileChange) {
                TextFileChange tf = (TextFileChange) change;
                TextEdit edit = tf.getEdit();
                IFile file = tf.getFile();
                String contents = AdtPlugin.readFile(file);
                assertEquals(contents, xml);
                if (edit instanceof MultiTextEdit) {
                    MultiTextEdit edits = (MultiTextEdit) edit;
                    edits.apply(document);
                } else {
                    edit.apply(document);
                }
            } else {
                System.out.println("Ignoring non-textfilechange in refactoring result");
            }
        }

        String actual = document.get();

        // Ensure that the document is still valid to make sure the edits don't
        // mangle it:
        org.w3c.dom.Document doc = DomUtilities.parseDocument(actual, true);
        assertNotNull(actual, doc);

        assertEqualsGolden(basename, actual);
    }

    protected void checkEdits(List<Change> changes,
            Map<IPath, String> fileToGoldenName) throws BadLocationException, IOException {
        checkEdits(changes, fileToGoldenName, false);
    }

    protected void checkEdits(List<Change> changes,
            Map<IPath, String> fileToGoldenName, boolean createDiffs)
                    throws BadLocationException, IOException {
        for (Change change : changes) {
            if (change instanceof TextFileChange) {
                TextFileChange tf = (TextFileChange) change;
                IFile file = tf.getFile();
                assertNotNull(file);
                IPath path = file.getProjectRelativePath();
                String goldenName = fileToGoldenName.get(path);
                assertNotNull("Not found: " + path.toString(), goldenName);

                String xml = readTestFile(goldenName, false);
                if (xml == null) { // New file
                    xml = ""; //$NON-NLS-1$
                }
                IDocument document = new Document();
                document.set(xml);

                String before = document.get();

                TextEdit edit = tf.getEdit();
                if (edit instanceof MultiTextEdit) {
                    MultiTextEdit edits = (MultiTextEdit) edit;
                    edits.apply(document);
                } else {
                    edit.apply(document);
                }

                String actual = document.get();

                if (createDiffs) {
                    // Use a diff as the golden file instead of the after
                    actual = getDiff(before, actual);
                    if (goldenName.endsWith(DOT_XML)) {
                        goldenName = goldenName.substring(0,
                                goldenName.length() - DOT_XML.length())
                                + ".diff";
                    }
                }

                assertEqualsGolden(goldenName, actual);
            } else {
                System.out.println("Ignoring non-textfilechange in refactoring result");
                assertNull(change.getAffectedObjects());
            }
        }
    }

    protected UiViewElementNode createModel(UiViewElementNode parent, Element element) {
        List<Element> children = DomUtilities.getChildren(element);
        String fqcn = ANDROID_WIDGET_PREFIX + element.getTagName();
        boolean hasChildren = children.size() > 0;
        UiViewElementNode node = createNode(parent, fqcn, hasChildren);
        node.setXmlNode(element);
        for (Element child : children) {
            createModel(node, child);
        }

        return node;
    }

    /**
     * Builds up a ViewInfo hierarchy for the given model. This is done by
     * reading .info dump files which record the exact pixel sizes of each
     * ViewInfo object. These files are assumed to match up exactly with the
     * model objects. This is done rather than rendering an actual layout
     * hierarchy to insulate the test from pixel difference (in say font size)
     * among platforms, as well as tying the test to particulars about relative
     * sizes of things which may change with theme adjustments etc.
     * <p>
     * Each file can be generated by the dump method in the ViewHierarchy.
     */
    protected ViewInfo createInfos(UiElementNode model, String relativePath) throws IOException {
        String basename = relativePath.substring(0, relativePath.lastIndexOf('.') + 1);
        String relative = basename + "info"; //$NON-NLS-1$
        String info = readTestFile(relative, true);
        // Parse the info file and build up a model from it
        // Each line contains a new info.
        // If indented it is a child of the parent.
        String[] lines = info.split("\n"); //$NON-NLS-1$

        // Iteration order for the info file should match exactly the UI model so
        // we can just advance the line index sequentially as we traverse

        return create(model, Arrays.asList(lines).iterator());
    }

    protected ViewInfo create(UiElementNode node, Iterator<String> lineIterator) {
        // android.widget.LinearLayout [0,36,240,320]
        Pattern pattern = Pattern.compile("(\\s*)(\\S+) \\[(\\d+),(\\d+),(\\d+),(\\d+)\\].*");
        assertTrue(lineIterator.hasNext());
        String description = lineIterator.next();
        Matcher matcher = pattern.matcher(description);
        assertTrue(matcher.matches());
        //String indent = matcher.group(1);
        //String fqcn = matcher.group(2);
        String left = matcher.group(3);
        String top = matcher.group(4);
        String right = matcher.group(5);
        String bottom = matcher.group(6);

        ViewInfo view = new ViewInfo(node.getXmlNode().getLocalName(), node,
                Integer.parseInt(left), Integer.parseInt(top),
                Integer.parseInt(right), Integer.parseInt(bottom));

        List<UiElementNode> childNodes = node.getUiChildren();
        if (childNodes.size() > 0) {
            List<ViewInfo> children = new ArrayList<ViewInfo>();
            for (UiElementNode child : childNodes) {
                children.add(create(child, lineIterator));
            }
            view.setChildren(children);
        }

        return view;
    }

    protected TestContext setupTestContext(IFile file, String relativePath) throws Exception {
        IStructuredModel structuredModel = null;
        org.w3c.dom.Document domDocument = null;
        IStructuredDocument structuredDocument = null;
        Element element = null;

        try {
            IModelManager modelManager = StructuredModelManager.getModelManager();
            structuredModel = modelManager.getModelForRead(file);
            if (structuredModel instanceof IDOMModel) {
                IDOMModel domModel = (IDOMModel) structuredModel;
                domDocument = domModel.getDocument();
                element = domDocument.getDocumentElement();
                structuredDocument = structuredModel.getStructuredDocument();
            }
        } finally {
            if (structuredModel != null) {
                structuredModel.releaseFromRead();
            }
        }

        assertNotNull(structuredModel);
        assertNotNull(domDocument);
        assertNotNull(element);
        assertNotNull(structuredDocument);
        assertTrue(element instanceof IndexedRegion);

        UiViewElementNode model = createModel(null, element);
        ViewInfo info = createInfos(model, relativePath);
        CanvasViewInfo rootView = CanvasViewInfo.create(info, true /* layoutlib5 */).getFirst();
        TestLayoutEditorDelegate layoutEditor =
            new TestLayoutEditorDelegate(file, structuredDocument, null);

        TestContext testInfo = createTestContext();
        testInfo.mFile = file;
        testInfo.mStructuredModel = structuredModel;
        testInfo.mStructuredDocument = structuredDocument;
        testInfo.mElement = element;
        testInfo.mDomDocument = domDocument;
        testInfo.mUiModel = model;
        testInfo.mViewInfo = info;
        testInfo.mRootView = rootView;
        testInfo.mLayoutEditorDelegate = layoutEditor;

        return testInfo;
    }

    protected TestContext createTestContext() {
        return new TestContext();
    }

    protected static class TestContext {
        protected IFile mFile;
        protected IStructuredModel mStructuredModel;
        protected IStructuredDocument mStructuredDocument;
        protected org.w3c.dom.Document mDomDocument;
        protected Element mElement;
        protected UiViewElementNode mUiModel;
        protected ViewInfo mViewInfo;
        protected CanvasViewInfo mRootView;
        protected TestLayoutEditorDelegate mLayoutEditorDelegate;
    }

    @Override
    public void testDummy() {
        // To avoid JUnit warning that this class contains no tests, even though
        // this is an abstract class and JUnit shouldn't try
    }
}
