/*
 * 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.build;

import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.AdtProjectTest;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;

import java.io.File;
import java.util.Collections;
import java.util.List;

public class AaptParserTest extends AdtProjectTest {

    public void testBasic() throws Exception {
        // Test the "at 'property' with value 'value' range matching included with most aapt errors
        checkRanges("quickfix1.xml", "res/layout/quickfix1.xml",
                "quickfix1.xml:7: error: Error: No resource found that matches the given name (at"
                + " 'text' with value '@string/firststring').",
                "android:text=\"^@string/firststring\"",
                "android:text=\"@string/firststring^\"");
    }

    public void testRange1() throws Exception {
        // Check that when the actual aapt error occurs on a line later than the original error
        // line, the forward search which looks for a value match does not stop on an
        // earlier line that happens to have the same value prefix
        checkRanges("aapterror1.xml", "res/layout/aapterror1.xml",
                "aapterror1.xml:5: error: Error: Integer types not allowed (at "
                + "'layout_marginBottom' with value '50').",
                "marginBottom=\"^50\"", "marginBottom=\"50^\"");
    }

    public void testRange2() throws Exception {
        // Check that when we have a duplicate resource error, we highlight both the original
        // property and the original definition.
        // This tests the second, duplicate declaration ration.
        checkRanges("aapterror2.xml", "res/values/aapterror2.xml",
                "aapterror2.xml:7: error: Resource entry repeatedStyle1 already has bag item "
                + "android:gravity.",
                "<item name=\"^android:gravity\">bottom</item>",
                "<item name=\"android:gravity^\">bottom</item>");
    }

    public void testRange3() throws Exception {
        // Check that when we have a duplicate resource error, we highlight both the original
        // property and the original definition.
        // This tests the original definition. Note that we don't have enough position info
        // so we simply highlight the whitespace portion of the line.
        checkRanges("aapterror2.xml", "res/values/aapterror2.xml",
                "aapterror2.xml:4: Originally defined here.",
                "^<item name=\"android:gravity\">left</item>",
                "<item name=\"android:gravity\">left</item>^");
    }

    public void testRange4() throws Exception {
        // Check for aapt error which occurs when the attribute name in an item style declaration
        // is nonexistent
        checkRanges("aapterror3.xml", "res/values/aapterror3.xml",
                "aapterror3.xml:4: error: Error: No resource found that matches the given name: "
                + "attr 'nonexistent'.",
                "<item name=\"^nonexistent\">5</item>",
                "<item name=\"nonexistent^\">5</item>");
    }

    public void testRange5() throws Exception {
        // Test missing resource name
        checkRanges("aapterror4.xml", "res/values/aapterror4.xml",
                "aapterror4.xml:3: error: A 'name' attribute is required for <style>",
                "<^style>",
                "<style^>");
    }

    public void testRange6() throws Exception {
        checkRanges("aapterror4.xml", "res/values/aapterror4.xml",
                "aapterror4.xml:6: error: A 'type' attribute is required for <item>",
                "<^item></item>",
                "<item^></item>");
    }

    public void testRange7() throws Exception {
        // Test missing resource name
        checkRanges("aapterror4.xml", "res/values/aapterror4.xml",
                "aapterror4.xml:6: error: A 'name' attribute is required for <item>",
                "<^item></item>",
                "<item^></item>");
    }

    // This test is disabled because I can't find a useful scenario for handling this error
    // message. When this error occurs, we will also get a warning on a missing attribute, and
    // that warning already underlines the element name.
    //public void testRange8() throws Exception {
    //    // Test missing resource name
    //    checkRanges("aapterror4.xml", "res/values/aapterror4.xml",
    //           "aapterror4.xml:4: error: Error: Resource id cannot be an empty string: attr ''.",
    //           "        ^<item />",
    //           "        <item />^");
    //}

    public void testRange9() throws Exception {
        // Test missing resource name
        checkRanges("aapterror5.xml", "res/values/aapterror5.xml",
                "aapterror5.xml:4: error: Error: String types not allowed (at "
                + "'android:layout_width' with value '').",
                "        <item name=\"^android:layout_width\"></item>",
                "        <item name=\"android:layout_width^\"></item>");
    }

    public void testRange10() throws Exception {
        // Test missing resource name
        checkRanges("aapterror6.xml", "res/layout/aapterror6.xml",
                "aapterror6.xml:5: error: Error: String types not allowed (at 'layout_marginTop'"
                + " with value '').",
                "android:layout_marginTop=^\"\"",
                "android:layout_marginTop=\"\"^");
    }

    public void testRange11() throws Exception {
        // Test missing resource name
        checkRanges("aapterror6.xml", "res/layout/aapterror6.xml",
                "aapterror1.xml:5: error: Error: String types not allowed (at 'layout_marginLeft'"
                + " with value '').",
                "android:layout_marginLeft=^''",
                "android:layout_marginLeft=''^");
    }

    public void testRange12() throws Exception {
        // Test missing resource name
        checkRanges("aapterror7.xml", "res/layout/aapterror7.xml",
                "aapterror7.xml:5: error: Error: String types not allowed (at 'id'"
                + " with value '').",
                "android:id=^\"\"",
                "android:id=\"\"^");
    }

    private void checkRanges(String name, String destPath, String aaptError,
            String expectCaretBegin, String expectCaretEnd)
            throws Exception {
        IProject project = getProject();
        IFile file = getTestDataFile(project, name, destPath);

        // Make file paths absolute
        String osRoot = project.getLocation().toOSString();
        String fileRelativePath = file.getProjectRelativePath().toPortableString();
        String filePath = osRoot + File.separator + fileRelativePath;
        String originalError = filePath + aaptError.substring(aaptError.indexOf(':'));
        List<String> errors = Collections.singletonList(originalError);

        // Remove anything already placed there by the project create/build automatic
        // (this usually only happens while debugging so the background thread has a chance
        // to get things going)
        IMarker[] markers = file.findMarkers(AdtConstants.MARKER_AAPT_COMPILE, true,
                IResource.DEPTH_ZERO);
        for (IMarker marker : markers) {
            marker.delete();
        }

        AaptParser.parseOutput(errors, project);
        markers = file.findMarkers(AdtConstants.MARKER_AAPT_COMPILE, true,
                IResource.DEPTH_ZERO);
        assertNotNull(markers);
        assertEquals(1, markers.length);

        String fileContents = AdtPlugin.readFile(file);
        int rangeBegin = getCaretOffset(file, expectCaretBegin);
        int rangeEnd = getCaretOffset(file, expectCaretEnd);

        // Check text range
        IMarker marker = markers[0];
        String message = marker.getAttribute(IMarker.MESSAGE, ""); //$NON-NLS-1$
        String simplerMessage = aaptError.substring(aaptError.indexOf(' ') + 1);
        assertEquals(simplerMessage, message);
        int start = marker.getAttribute(IMarker.CHAR_START, 0);
        int end = marker.getAttribute(IMarker.CHAR_END, 0);

        assertEquals("Wrong start offset, expected " + expectCaretBegin + " but was "
                + getCaretContext(fileContents, start), rangeBegin, start);
        assertEquals("Wrong end offset, expected " + expectCaretEnd + " but was "
                + getCaretContext(fileContents, end), rangeEnd, end);
    }
}
