/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.ArrayList;

public class Comment
{
    static final Pattern LEADING_WHITESPACE = Pattern.compile(
                                "^[ \t\n\r]*(.*)$",
                                Pattern.DOTALL);

    static final Pattern TAG_BEGIN = Pattern.compile(
                                "[\r\n][\r\n \t]*@",
                                Pattern.DOTALL);

    static final Pattern TAG = Pattern.compile(
                                "(@[^ \t\r\n]+)[ \t\r\n]+(.*)",
                                Pattern.DOTALL);

    static final Pattern INLINE_TAG = Pattern.compile(
                                "(.*?)\\{(@[^ \t\r\n\\}]+)[ \t\r\n]*(.*?)\\}",
                                Pattern.DOTALL);

    static final Pattern FIRST_SENTENCE = Pattern.compile(
                                "((.*?)\\.)[ \t\r\n\\<](.*)",
                                Pattern.DOTALL);

    private static final String[] KNOWN_TAGS = new String[] {
            "@author",
            "@since",
            "@version",
            "@deprecated",
            "@undeprecate",
            "@docRoot",
            "@sdkCurrent",
            "@inheritDoc",
            "@more",
            "@code",
            "@samplecode",
            "@sample",
            "@include",
            "@serial",
        };

    public Comment(String text, ContainerInfo base, SourcePositionInfo sp)
    {
        mText = text;
        mBase = base;
        // sp now points to the end of the text, not the beginning!
        mPosition = SourcePositionInfo.findBeginning(sp, text);
    }

    private void parseRegex(String text)
    {
        Matcher m;

        m = LEADING_WHITESPACE.matcher(text);
        m.matches();
        text = m.group(1);

        m = TAG_BEGIN.matcher(text);

        int start = 0;
        int end = 0;
        while (m.find()) {
            end = m.start();

            tag(text, start, end);

            start = m.end()-1; // -1 is the @
        }
        end = text.length();
        tag(text, start, end);
    }

    private void tag(String text, int start, int end)
    {
        SourcePositionInfo pos = SourcePositionInfo.add(mPosition, mText, start);

        if (start >= 0 && end > 0 && (end-start) > 0) {
            text = text.substring(start, end);

            Matcher m = TAG.matcher(text);
            if (m.matches()) {
                // out of line tag
                tag(m.group(1), m.group(2), false, pos);
            } else {
                // look for inline tags
                m = INLINE_TAG.matcher(text);
                start = 0;
                while (m.find()) {
                    String str = m.group(1);
                    String tagname = m.group(2);
                    String tagvalue = m.group(3);
                    tag(null, m.group(1), true, pos);
                    tag(tagname, tagvalue, true, pos);
                    start = m.end();
                }
                int len = text.length();
                if (start != len) {
                    tag(null, text.substring(start), true, pos);
                }
            }
        }
    }

    private void tag(String name, String text, boolean isInline, SourcePositionInfo pos)
    {
        /*
        String s = isInline ? "inline" : "outofline";
        System.out.println("---> " + s
                + " name=[" + name + "] text=[" + text + "]");
        */
        if (name == null) {
            mInlineTagsList.add(new TextTagInfo("Text", "Text", text, pos));
        }
        else if (name.equals("@param")) {
            mParamTagsList.add(new ParamTagInfo("@param", "@param", text, mBase, pos));
        }
        else if (name.equals("@see")) {
            mSeeTagsList.add(new SeeTagInfo("@see", "@see", text, mBase, pos));
        }
        else if (name.equals("@link") || name.equals("@linkplain")) {
            mInlineTagsList.add(new SeeTagInfo(name, "@see", text, mBase, pos));
        }
        else if (name.equals("@throws") || name.equals("@exception")) {
            mThrowsTagsList.add(new ThrowsTagInfo("@throws", "@throws", text, mBase, pos));
        }
        else if (name.equals("@return")) {
            mReturnTagsList.add(new ParsedTagInfo("@return", "@return", text, mBase, pos));
        }
        else if (name.equals("@deprecated")) {
            if (text.length() == 0) {
                Errors.error(Errors.MISSING_COMMENT, pos,
                        "@deprecated tag with no explanatory comment");
                text = "No replacement.";
            }
            mDeprecatedTagsList.add(new ParsedTagInfo("@deprecated", "@deprecated", text, mBase, pos));
        }
        else if (name.equals("@literal")) {
            mInlineTagsList.add(new LiteralTagInfo(name, name, text, pos));
        }
        else if (name.equals("@hide") || name.equals("@pending") || name.equals("@doconly")) {
            // nothing
        }
        else if (name.equals("@attr")) {
            AttrTagInfo tag = new AttrTagInfo("@attr", "@attr", text, mBase, pos);
            mAttrTagsList.add(tag);
            Comment c = tag.description();
            if (c != null) {
                for (TagInfo t: c.tags()) {
                    mInlineTagsList.add(t);
                }
            }
        }
        else if (name.equals("@undeprecate")) {
            mUndeprecateTagsList.add(new TextTagInfo("@undeprecate", "@undeprecate", text, pos));
        }
        else if (name.equals("@include") || name.equals("@sample")) {
            mInlineTagsList.add(new SampleTagInfo(name, "@include", text, mBase, pos));
        }
        else {
            boolean known = false;
            for (String s: KNOWN_TAGS) {
                if (s.equals(name)) {
                    known = true;
                    break;
                }
            }
            if (!known) {
                known = DroidDoc.knownTags.contains(name);
            }
            if (!known) {
                Errors.error(Errors.UNKNOWN_TAG, pos == null ? null : new SourcePositionInfo(pos),
                        "Unknown tag: " + name);
            }
            TagInfo t = new TextTagInfo(name, name, text, pos);
            if (isInline) {
                mInlineTagsList.add(t);
            } else {
                mTagsList.add(t);
            }
        }
    }

    private void parseBriefTags()
    {
        int N = mInlineTagsList.size();

        // look for "@more" tag, which means that we might go past the first sentence.
        int more = -1;
        for (int i=0; i<N; i++) {
            if (mInlineTagsList.get(i).name().equals("@more")) {
                more = i;
            }
        }
          if (more >= 0) {
            for (int i=0; i<more; i++) {
                mBriefTagsList.add(mInlineTagsList.get(i));
            }
        } else {
            for (int i=0; i<N; i++) {
                TagInfo t = mInlineTagsList.get(i);
                if (t.name().equals("Text")) {
                    Matcher m = FIRST_SENTENCE.matcher(t.text());
                    if (m.matches()) {
                        String text = m.group(1);
                        TagInfo firstSentenceTag = new TagInfo(t.name(), t.kind(), text, t.position());
                        mBriefTagsList.add(firstSentenceTag);
                        break;
                    }
                }
                mBriefTagsList.add(t);

            }
        }
    }

    public TagInfo[] tags()
    {
        init();
        return mInlineTags;
    }

    public TagInfo[] tags(String name)
    {
        init();
        ArrayList<TagInfo> results = new ArrayList<TagInfo>();
        int N = mInlineTagsList.size();
        for (int i=0; i<N; i++) {
            TagInfo t = mInlineTagsList.get(i);
            if (t.name().equals(name)) {
                results.add(t);
            }
        }
        return results.toArray(new TagInfo[results.size()]);
    }

    public ParamTagInfo[] paramTags()
    {
        init();
        return mParamTags;
    }

    public SeeTagInfo[] seeTags()
    {
        init();
        return mSeeTags;
    }

    public ThrowsTagInfo[] throwsTags()
    {
        init();
        return mThrowsTags;
    }

    public TagInfo[] returnTags()
    {
        init();
        return mReturnTags;
    }

    public TagInfo[] deprecatedTags()
    {
        init();
        return mDeprecatedTags;
    }

    public TagInfo[] undeprecateTags()
    {
        init();
        return mUndeprecateTags;
    }

    public AttrTagInfo[] attrTags()
    {
        init();
        return mAttrTags;
    }

    public TagInfo[] briefTags()
    {
        init();
        return mBriefTags;
    }

    public boolean isHidden()
    {
        if (mHidden >= 0) {
            return mHidden != 0;
        } else {
            if (DroidDoc.checkLevel(DroidDoc.SHOW_HIDDEN)) {
                mHidden = 0;
                return false;
            }
            boolean b = mText.indexOf("@hide") >= 0 || mText.indexOf("@pending") >= 0;
            mHidden = b ? 1 : 0;
            return b;
        }
    }

    public boolean isDocOnly() {
        if (mDocOnly >= 0) {
            return mDocOnly != 0;
        } else {
            boolean b = (mText != null) && (mText.indexOf("@doconly") >= 0);
            mDocOnly = b ? 1 : 0;
            return b;
        }
    }

    private void init()
    {
        if (!mInitialized) {
            initImpl();
        }
    }

    private void initImpl()
    {
        isHidden();
        isDocOnly();

        // Don't bother parsing text if we aren't generating documentation.
        if (DroidDoc.parseComments()) {
            parseRegex(mText);
            parseBriefTags();
        } else {
          // Forces methods to be recognized by findOverriddenMethods in MethodInfo.
          mInlineTagsList.add(new TextTagInfo("Text", "Text", mText,
                  SourcePositionInfo.add(mPosition, mText, 0)));
        }

        mText = null;
        mInitialized = true;

        mInlineTags = mInlineTagsList.toArray(new TagInfo[mInlineTagsList.size()]);
        mParamTags = mParamTagsList.toArray(new ParamTagInfo[mParamTagsList.size()]);
        mSeeTags = mSeeTagsList.toArray(new SeeTagInfo[mSeeTagsList.size()]);
        mThrowsTags = mThrowsTagsList.toArray(new ThrowsTagInfo[mThrowsTagsList.size()]);
        mReturnTags = ParsedTagInfo.joinTags(mReturnTagsList.toArray(
                                             new ParsedTagInfo[mReturnTagsList.size()]));
        mDeprecatedTags = ParsedTagInfo.joinTags(mDeprecatedTagsList.toArray(
                                        new ParsedTagInfo[mDeprecatedTagsList.size()]));
        mUndeprecateTags = mUndeprecateTagsList.toArray(new TagInfo[mUndeprecateTagsList.size()]);
        mAttrTags = mAttrTagsList.toArray(new AttrTagInfo[mAttrTagsList.size()]);
        mBriefTags = mBriefTagsList.toArray(new TagInfo[mBriefTagsList.size()]);

        mParamTagsList = null;
        mSeeTagsList = null;
        mThrowsTagsList = null;
        mReturnTagsList = null;
        mDeprecatedTagsList = null;
        mUndeprecateTagsList = null;
        mAttrTagsList = null;
        mBriefTagsList = null;
    }

    boolean mInitialized;
    int mHidden = -1;
    int mDocOnly = -1;
    String mText;
    ContainerInfo mBase;
    SourcePositionInfo mPosition;
    int mLine = 1;

    TagInfo[] mInlineTags;
    TagInfo[] mTags;
    ParamTagInfo[] mParamTags;
    SeeTagInfo[] mSeeTags;
    ThrowsTagInfo[] mThrowsTags;
    TagInfo[] mBriefTags;
    TagInfo[] mReturnTags;
    TagInfo[] mDeprecatedTags;
    TagInfo[] mUndeprecateTags;
    AttrTagInfo[] mAttrTags;

    ArrayList<TagInfo> mInlineTagsList = new ArrayList<TagInfo>();
    ArrayList<TagInfo> mTagsList = new ArrayList<TagInfo>();
    ArrayList<ParamTagInfo> mParamTagsList = new ArrayList<ParamTagInfo>();
    ArrayList<SeeTagInfo> mSeeTagsList = new ArrayList<SeeTagInfo>();
    ArrayList<ThrowsTagInfo> mThrowsTagsList = new ArrayList<ThrowsTagInfo>();
    ArrayList<TagInfo> mBriefTagsList = new ArrayList<TagInfo>();
    ArrayList<ParsedTagInfo> mReturnTagsList = new ArrayList<ParsedTagInfo>();
    ArrayList<ParsedTagInfo> mDeprecatedTagsList = new ArrayList<ParsedTagInfo>();
    ArrayList<TagInfo> mUndeprecateTagsList = new ArrayList<TagInfo>();
    ArrayList<AttrTagInfo> mAttrTagsList = new ArrayList<AttrTagInfo>();


}
