/*
 * 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.FD_RES;
import static com.android.SdkConstants.FD_RES_LAYOUT;
import static com.android.SdkConstants.FD_RES_VALUES;

import com.android.ide.common.sdk.LoadStatus;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AdtUtils;
import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors;
import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectCreator;
import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardState;
import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardState.Mode;
import com.android.ide.eclipse.tests.SdkLoadingTestCase;
import com.android.sdklib.IAndroidTarget;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.swt.graphics.Point;
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.text.IStructuredDocument;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SuppressWarnings({"restriction", "javadoc"})
public abstract class AdtProjectTest extends SdkLoadingTestCase {
    private static final int TARGET_API_LEVEL = 16;
    public static final String TEST_PROJECT_PACKAGE = "com.android.eclipse.tests"; //$NON-NLS-1$
    private static final long TESTS_START_TIME = System.currentTimeMillis();
    private static final String PROJECTNAME_PREFIX = "testproject-";

    /**
     * We don't stash the project used by each test case as a field such that test cases
     * can share a single project instance (which is typically much faster).
     * However, see {@link #getProjectName()} for exceptions to this sharing scheme.
     */
    private static Map<String, IProject> sProjectMap = new HashMap<String, IProject>();

    @Override
    protected String getTestDataRelPath() {
        return "eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/"
                + "internal/editors/layout/refactoring/testdata";
    }

    @Override
    protected InputStream getTestResource(String relativePath, boolean expectExists) {
        String path = "testdata" + File.separator + relativePath; //$NON-NLS-1$
        InputStream stream =
            AdtProjectTest.class.getResourceAsStream(path);
        if (!expectExists && stream == null) {
            return null;
        }
        return stream;
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        // Prevent preview icon computation during plugin test to make test faster
        if (AdtPlugin.getDefault() == null) {
            fail("This test must be run as an Eclipse plugin test, not a plain JUnit test!");
        }
        AdtPrefs.getPrefs().setPaletteModes("ICON_TEXT"); //$NON-NLS-1$

        getProject();

        Sdk current = Sdk.getCurrent();
        assertNotNull(current);
        LoadStatus sdkStatus = AdtPlugin.getDefault().getSdkLoadStatus();
        assertSame(LoadStatus.LOADED, sdkStatus);
        IAndroidTarget target = current.getTarget(getProject());
        IJavaProject javaProject = BaseProjectHelper.getJavaProject(getProject());
        assertNotNull(javaProject);
        int iterations = 0;
        while (true) {
            if (iterations == 100) {
                fail("Couldn't load target; ran out of time");
            }
            LoadStatus status = current.checkAndLoadTargetData(target, javaProject);
            if (status == LoadStatus.FAILED) {
                fail("Couldn't load target " + target);
            }
            if (status != LoadStatus.LOADING) {
                break;
            }
            Thread.sleep(250);
            iterations++;
        }
        AndroidTargetData targetData = current.getTargetData(target);
        assertNotNull(targetData);
        LayoutDescriptors layoutDescriptors = targetData.getLayoutDescriptors();
        assertNotNull(layoutDescriptors);
        List<ViewElementDescriptor> viewDescriptors = layoutDescriptors.getViewDescriptors();
        assertNotNull(viewDescriptors);
        assertTrue(viewDescriptors.size() > 0);
        List<ViewElementDescriptor> layoutParamDescriptors =
                layoutDescriptors.getLayoutDescriptors();
        assertNotNull(layoutParamDescriptors);
        assertTrue(layoutParamDescriptors.size() > 0);
    }

    /** Set to true if the subclass test case should use a per-instance project rather
     * than a shared project. This is needed by projects which modify the project in such
     * a way that it affects what other tests see (for example, the quickfix resource creation
     * tests will add in new resources, which the code completion tests will then list as
     * possible matches if the code completion test is run after the quickfix test.)
     * @return true to create a per-instance project instead of the default shared project
     */
    protected boolean testCaseNeedsUniqueProject() {
        return false;
    }

    protected boolean testNeedsUniqueProject() {
        return false;
    }

    @Override
    protected boolean validateSdk(IAndroidTarget target) {
        // Not quite working yet. When enabled will make tests run faster.
        //if (target.getVersion().getApiLevel() < TARGET_API_LEVEL) {
        //    return false;
        //}

        return true;
    }

    /** Returns a name to use for the project used in this test. Subclasses do not need to
     * override this if they can share a project with others - which is the case if they do
     * not modify the project in a way that does not affect other tests. For example
     * the resource quickfix test will create new resources which affect what shows up
     * in the code completion results, so the quickfix tests will override this method
     * to produce a unique project for its own tests.
     */
    private String getProjectName() {
        if (testNeedsUniqueProject()) {
            return PROJECTNAME_PREFIX + getClass().getSimpleName() + "-" + getName();
        } else if (testCaseNeedsUniqueProject()) {
            return PROJECTNAME_PREFIX + getClass().getSimpleName();
        } else {
            return PROJECTNAME_PREFIX + TESTS_START_TIME;
        }
    }

    protected IProject getProject() {
        String projectName = getProjectName();
        IProject project = sProjectMap.get(projectName);
        if (project == null) {
            project = createProject(projectName);
            assertNotNull(project);
            sProjectMap.put(projectName, project);
        }
        if (!testCaseNeedsUniqueProject() && !testNeedsUniqueProject()) {
            addCleanupDir(AdtUtils.getAbsolutePath(project).toFile());
        }
        addCleanupDir(project.getFullPath().toFile());
        return project;
    }

    protected IFile getTestDataFile(IProject project, String name) throws Exception {
        return getTestDataFile(project, name, name);
    }

    protected IFile getLayoutFile(IProject project, String name) throws Exception {
        return getTestDataFile(project, name, FD_RES + "/" + FD_RES_LAYOUT + "/" + name);
    }

    protected IFile getValueFile(IProject project, String name) throws Exception {
        return getTestDataFile(project, name, FD_RES + "/" + FD_RES_VALUES + "/" + name);
    }

    protected IFile getTestDataFile(IProject project, String sourceName,
            String destPath) throws Exception {
        return getTestDataFile(project, sourceName, destPath, false);
    }

    protected IFile getTestDataFile(IProject project, String sourceName,
            String destPath, boolean overwrite) throws Exception {
        String[] split = destPath.split("/"); //$NON-NLS-1$
        IContainer parent;
        String name;
        if (split.length == 1) {
            parent = project;
            name = destPath;
        } else {
            IFolder folder = project.getFolder(split[0]);
            NullProgressMonitor monitor = new NullProgressMonitor();
            if (!folder.exists()) {
                folder.create(true /* force */, true /* local */, monitor);
            }
            for (int i = 1, n = split.length; i < n -1; i++) {
                IFolder subFolder = folder.getFolder(split[i]);
                if (!subFolder.exists()) {
                    subFolder.create(true /* force */, true /* local */, monitor);
                }
                folder = subFolder;
            }
            name = split[split.length - 1];
            parent = folder;
        }
        IFile file = parent.getFile(new Path(name));
        if (overwrite && file.exists()) {
            String currentContents = AdtPlugin.readFile(file);
            String newContents = readTestFile(sourceName, true);
            if (currentContents == null || !currentContents.equals(newContents)) {
                file.delete(true, new NullProgressMonitor());
            } else {
                return file;
            }
        }
        if (!file.exists()) {
            String xml = readTestFile(sourceName, true);
            InputStream bstream = new ByteArrayInputStream(xml.getBytes("UTF-8")); //$NON-NLS-1$
            NullProgressMonitor monitor = new NullProgressMonitor();
            file.create(bstream, false /* force */, monitor);
        }

        return file;
    }

    protected IProject createProject(String name) {
        IAndroidTarget target = null;

        IAndroidTarget[] targets = getSdk().getTargets();
        for (IAndroidTarget t : targets) {
            if (!t.isPlatform()) {
                continue;
            }
            if (t.getVersion().getApiLevel() >= TARGET_API_LEVEL) {
                target = t;
                break;
            }
        }
        assertNotNull(target);

        IRunnableContext context = new IRunnableContext() {
            @Override
            public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable)
                    throws InvocationTargetException, InterruptedException {
                runnable.run(new NullProgressMonitor());
            }
        };
        NewProjectWizardState state = new NewProjectWizardState(Mode.ANY);
        state.projectName = name;
        state.target = target;
        state.packageName = TEST_PROJECT_PACKAGE;
        state.activityName = name;
        state.applicationName = name;
        state.createActivity = false;
        state.useDefaultLocation = true;
        if (getMinSdk() != -1) {
            state.minSdk = Integer.toString(getMinSdk());
        }

        NewProjectCreator creator = new NewProjectCreator(state, context);
        creator.createAndroidProjects();
        return validateProjectExists(name);
    }

    protected int getMinSdk() {
        return -1;
    }

    public void createTestProject() {
        IAndroidTarget target = null;

        IAndroidTarget[] targets = getSdk().getTargets();
        for (IAndroidTarget t : targets) {
            if (t.getVersion().getApiLevel() >= TARGET_API_LEVEL) {
                target = t;
                break;
            }
        }
        assertNotNull(target);
    }

    protected static IProject validateProjectExists(String name) {
        IProject iproject = getProject(name);
        assertTrue(String.format("%s project not created", name), iproject.exists());
        assertTrue(String.format("%s project not opened", name), iproject.isOpen());
        return iproject;
    }

    private static IProject getProject(String name) {
        IProject iproject = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
        return iproject;
    }

    protected int getCaretOffset(IFile file, String caretLocation) {
        assertTrue(caretLocation, caretLocation.contains("^"));

        String fileContent = AdtPlugin.readFile(file);
        return getCaretOffset(fileContent, caretLocation);
    }

    /**
     * If the given caret location string contains a selection range, select that range in
     * the given viewer
     *
     * @param viewer the viewer to contain the selection
     * @param caretLocation the location string
     */
    protected int updateCaret(ISourceViewer viewer, String caretLocation) {
        assertTrue(caretLocation, caretLocation.contains("^")); //$NON-NLS-1$

        int caretDelta = caretLocation.indexOf("^"); //$NON-NLS-1$
        assertTrue(caretLocation, caretDelta != -1);
        String text = viewer.getTextWidget().getText();

        int length = 0;

        // String around caret/range without the range and caret marker characters
        String caretContext;

        if (caretLocation.contains("[^")) { //$NON-NLS-1$
            caretDelta--;
            assertTrue(caretLocation, caretLocation.startsWith("[^", caretDelta)); //$NON-NLS-1$

            int caretRangeEnd = caretLocation.indexOf(']', caretDelta + 2);
            assertTrue(caretLocation, caretRangeEnd != -1);
            length = caretRangeEnd - caretDelta - 2;
            assertTrue(length > 0);
            caretContext = caretLocation.substring(0, caretDelta)
                    + caretLocation.substring(caretDelta + 2, caretRangeEnd)
                    + caretLocation.substring(caretRangeEnd + 1);
        } else {
            caretContext = caretLocation.substring(0, caretDelta)
                    + caretLocation.substring(caretDelta + 1); // +1: skip "^"
        }

        int caretContextIndex = text.indexOf(caretContext);

        assertTrue("Caret content " + caretContext + " not found in file",
                caretContextIndex != -1);

        int offset = caretContextIndex + caretDelta;
        viewer.setSelectedRange(offset, length);

        return offset;
    }

    protected String addSelection(String newFileContents, Point selectedRange) {
        int selectionBegin = selectedRange.x;
        int selectionEnd = selectionBegin + selectedRange.y;
        return addSelection(newFileContents, selectionBegin, selectionEnd);
    }

    @Override
    protected String removeSessionData(String data) {
        data = super.removeSessionData(data);
        if (getProject() != null) {
            data = data.replace(getProject().getName(), "PROJECTNAME");
        }

        return data;
    }

    public static ViewElementDescriptor createDesc(String name, String fqn, boolean hasChildren) {
        if (hasChildren) {
            return new ViewElementDescriptor(name, name, fqn, "", "", new AttributeDescriptor[0],
                    new AttributeDescriptor[0], new ElementDescriptor[1], false);
        } else {
            return new ViewElementDescriptor(name, fqn);
        }
    }

    public static UiViewElementNode createNode(UiViewElementNode parent, String fqn,
            boolean hasChildren) {
        String name = fqn.substring(fqn.lastIndexOf('.') + 1);
        ViewElementDescriptor descriptor = createDesc(name, fqn, hasChildren);
        if (parent == null) {
            // All node hierarchies should be wrapped inside a document node at the root
            parent = new UiViewElementNode(createDesc("doc", "doc", true));
        }
        return (UiViewElementNode) parent.appendNewUiChild(descriptor);
    }

    public static UiViewElementNode createNode(String fqn, boolean hasChildren) {
        return createNode(null, fqn, hasChildren);
    }

    /** Special editor context set on the model to be rendered */
    protected static class TestLayoutEditorDelegate extends LayoutEditorDelegate {

        public TestLayoutEditorDelegate(
                IFile file,
                IStructuredDocument structuredDocument,
                UiDocumentNode uiRootNode) {
            super(new TestAndroidXmlCommonEditor(file, structuredDocument, uiRootNode));
        }

        static class TestAndroidXmlCommonEditor extends CommonXmlEditor {

            private final IFile mFile;
            private final IStructuredDocument mStructuredDocument;
            private UiDocumentNode mUiRootNode;

            TestAndroidXmlCommonEditor(
                    IFile file,
                    IStructuredDocument structuredDocument,
                    UiDocumentNode uiRootNode) {
                mFile = file;
                mStructuredDocument = structuredDocument;
                mUiRootNode = uiRootNode;
            }

            @Override
            public IFile getInputFile() {
                return mFile;
            }

            @Override
            public IProject getProject() {
                return mFile.getProject();
            }

            @Override
            public IStructuredDocument getStructuredDocument() {
                return mStructuredDocument;
            }

            @Override
            public UiDocumentNode getUiRootNode() {
                return mUiRootNode;
            }

            @Override
            public void editorDirtyStateChanged() {
            }

            @Override
            public IStructuredModel getModelForRead() {
                IModelManager mm = StructuredModelManager.getModelManager();
                if (mm != null) {
                    try {
                        return mm.getModelForRead(mFile);
                    } catch (Exception e) {
                        fail(e.toString());
                    }
                }

                return null;
            }
        }
    }

    public void testDummy() {
        // This class contains shared test functionality for testcase subclasses,
        // but without an actual test in the class JUnit complains (even if we make
        // it abstract)
    }
}
