/*
 * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.tools.doclets.formats.html;

import com.sun.tools.doclets.internal.toolkit.util.*;
import com.sun.tools.doclets.internal.toolkit.taglets.*;

import com.sun.javadoc.*;
import java.util.*;
import java.lang.reflect.Modifier;

/**
 * The base class for member writers.
 *
 * @author Robert Field
 * @author Atul M Dambalkar
 * @author Jamie Ho (Re-write)
 */
public abstract class AbstractMemberWriter {

    protected boolean printedSummaryHeader = false;
    protected final SubWriterHolderWriter writer;
    protected final ClassDoc classdoc;
    public final boolean nodepr;

    public AbstractMemberWriter(SubWriterHolderWriter writer,
                             ClassDoc classdoc) {
        this.writer = writer;
        this.nodepr = configuration().nodeprecated;
        this.classdoc = classdoc;
    }

    public AbstractMemberWriter(SubWriterHolderWriter writer) {
        this(writer, null);
    }

    /*** abstracts ***/

    public abstract void printSummaryLabel(ClassDoc cd);

    public abstract void printInheritedSummaryLabel(ClassDoc cd);

    public abstract void printSummaryAnchor(ClassDoc cd);

    public abstract void printInheritedSummaryAnchor(ClassDoc cd);

    protected abstract void printSummaryType(ProgramElementDoc member);

    protected void writeSummaryLink(ClassDoc cd, ProgramElementDoc member) {
        writeSummaryLink(LinkInfoImpl.CONTEXT_MEMBER, cd, member);
    }

    protected abstract void writeSummaryLink(int context,
                                             ClassDoc cd,
                                             ProgramElementDoc member);

    protected abstract void writeInheritedSummaryLink(ClassDoc cd,
                                                     ProgramElementDoc member);

    protected abstract void writeDeprecatedLink(ProgramElementDoc member);

    protected abstract void printNavSummaryLink(ClassDoc cd, boolean link);

    protected abstract void printNavDetailLink(boolean link);

    /***  ***/

    protected void print(String str) {
        writer.print(str);
        writer.displayLength += str.length();
    }

    protected void print(char ch) {
        writer.print(ch);
        writer.displayLength++;
    }

    protected void bold(String str) {
        writer.bold(str);
        writer.displayLength += str.length();
    }

    /**
     * Return a string describing the access modifier flags.
     * Don't include native or synchronized.
     *
     * The modifier names are returned in canonical order, as
     * specified by <em>The Java Language Specification</em>.
     */
    protected String modifierString(MemberDoc member) {
        int ms = member.modifierSpecifier();
        int no = Modifier.NATIVE | Modifier.SYNCHRONIZED;
    return Modifier.toString(ms & ~no);
    }

    protected String typeString(MemberDoc member) {
        String type = "";
        if (member instanceof MethodDoc) {
            type = ((MethodDoc)member).returnType().toString();
        } else if (member instanceof FieldDoc) {
            type = ((FieldDoc)member).type().toString();
        }
        return type;
    }

    protected void printModifiers(MemberDoc member) {
        String mod = modifierString(member);
        // According to JLS, we should not be showing public modifier for
        // interface methods.
        if ((member.isField() || member.isMethod()) &&
            writer instanceof ClassWriterImpl &&
             ((ClassWriterImpl) writer).getClassDoc().isInterface()) {
            mod = Util.replaceText(mod, "public", "").trim();
        }
        if(mod.length() > 0) {
            print(mod);
            print(' ');
        }
    }

    protected String makeSpace(int len) {
        if (len <= 0) {
            return "";
        }
        StringBuffer sb = new StringBuffer(len);
        for(int i = 0; i < len; i++) {
            sb.append(' ');
    }
        return sb.toString();
    }

    /**
     * Print 'static' if static and type link.
     */
    protected void printStaticAndType(boolean isStatic, Type type) {
        writer.printTypeSummaryHeader();
        if (isStatic) {
            print("static");
        }
        writer.space();
        if (type != null) {
            writer.printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER,
                type));
        }
        writer.printTypeSummaryFooter();
    }

    /**
     * Print the modifier and type for the member in the member summary.
     *
     * @param member the member to print the type for.
     * @param type   the type to print.
     */
    protected void printModifierAndType(ProgramElementDoc member, Type type) {
        writer.printTypeSummaryHeader();
        printModifier(member);
        if (type == null) {
            writer.space();
            if (member.isClass()) {
                print("class");
            } else {
                print("interface");
            }
        } else {
            if (member instanceof ExecutableMemberDoc &&
                    ((ExecutableMemberDoc) member).typeParameters().length > 0) {
                //Code to avoid ugly wrapping in member summary table.
                writer.table(0,0,0);
                writer.trAlignVAlign("right", "");
                writer.tdNowrap();
                writer.font("-1");
                writer.code();
                int displayLength = ((AbstractExecutableMemberWriter) this).
                writeTypeParameters((ExecutableMemberDoc) member);
                if (displayLength > 10) {
                    writer.br();
                }
                writer.printLink(new LinkInfoImpl(
                    LinkInfoImpl.CONTEXT_SUMMARY_RETURN_TYPE, type));
                writer.codeEnd();
                writer.fontEnd();
                writer.tdEnd();
                writer.trEnd();
                writer.tableEnd();
            } else {
                writer.space();
                writer.printLink(new LinkInfoImpl(
                    LinkInfoImpl.CONTEXT_SUMMARY_RETURN_TYPE, type));
            }

        }
        writer.printTypeSummaryFooter();
    }

    private void printModifier(ProgramElementDoc member) {
        if (member.isProtected()) {
            print("protected ");
        } else if (member.isPrivate()) {
            print("private ");
        } else if (!member.isPublic()) { // Package private
            writer.printText("doclet.Package_private");
            print(" ");
        }
        if (member.isMethod() && ((MethodDoc)member).isAbstract()) {
            print("abstract ");
        }
        if (member.isStatic()) {
            print("static");
        }
    }

    protected void printComment(ProgramElementDoc member) {
        if (member.inlineTags().length > 0) {
            writer.dd();
            writer.printInlineComment(member);
        }
    }

    protected String name(ProgramElementDoc member) {
        return member.name();
    }

    protected void printHead(MemberDoc member) {
        writer.h3();
        writer.print(member.name());
        writer.h3End();
    }

    protected void printFullComment(ProgramElementDoc member) {
        if(configuration().nocomment){
            return;
        }
        writer.dl();
        print(((TagletOutputImpl)
            (new DeprecatedTaglet()).getTagletOutput(member,
            writer.getTagletWriterInstance(false))).toString());
        printCommentAndTags(member);
        writer.dlEnd();
    }

    protected void printCommentAndTags(ProgramElementDoc member) {
        printComment(member);
        writer.printTags(member);
    }

    /**
     * Forward to containing writer
     */
    public void printSummaryHeader(ClassDoc cd) {
        printedSummaryHeader = true;
        writer.printSummaryHeader(this, cd);
    }

    /**
     * Forward to containing writer
     */
    public void printInheritedSummaryHeader(ClassDoc cd) {
        writer.printInheritedSummaryHeader(this, cd);
    }

    /**
     * Forward to containing writer
     */
    public void printInheritedSummaryFooter(ClassDoc cd) {
        writer.printInheritedSummaryFooter(this, cd);
    }

    /**
     * Forward to containing writer
     */
    public void printSummaryFooter(ClassDoc cd) {
        writer.printSummaryFooter(this, cd);
    }

   /**
    * Return true if the given <code>ProgramElement</code> is inherited
    * by the class that is being documented.
    *
    * @param ped The <code>ProgramElement</code> being checked.
    * return true if the <code>ProgramElement</code> is being inherited and
    * false otherwise.
    */
    protected boolean isInherited(ProgramElementDoc ped){
        if(ped.isPrivate() || (ped.isPackagePrivate() &&
            ! ped.containingPackage().equals(classdoc.containingPackage()))){
            return false;
        }
        return true;
    }


    /**
     * Generate the code for listing the deprecated APIs. Create the table
     * format for listing the API. Call methods from the sub-class to complete
     * the generation.
     */
    protected void printDeprecatedAPI(List deprmembers, String headingKey) {
        if (deprmembers.size() > 0) {
            writer.tableIndexSummary();
            writer.tableHeaderStart("#CCCCFF");
            writer.boldText(headingKey);
            writer.tableHeaderEnd();
            for (int i = 0; i < deprmembers.size(); i++) {
                ProgramElementDoc member =(ProgramElementDoc)deprmembers.get(i);
                writer.trBgcolorStyle("white", "TableRowColor");
                writer.summaryRow(0);
                writeDeprecatedLink(member);
                writer.br();
                writer.printNbsps();
                if (member.tags("deprecated").length > 0)
                    writer.printInlineDeprecatedComment(member, member.tags("deprecated")[0]);
                writer.space();
                writer.summaryRowEnd();
                writer.trEnd();
            }
            writer.tableEnd();
            writer.space();
            writer.p();
        }
    }

    /**
     * Print use info.
     */
    protected void printUseInfo(List<? extends ProgramElementDoc> mems, String heading) {
        if (mems == null) {
            return;
        }
        List<? extends ProgramElementDoc> members = mems;
        if (members.size() > 0) {
            writer.tableIndexSummary();
            writer.tableUseInfoHeaderStart("#CCCCFF");
            writer.print(heading);
            writer.tableHeaderEnd();
            for (Iterator<? extends ProgramElementDoc> it = members.iterator(); it.hasNext(); ) {
                ProgramElementDoc pgmdoc = it.next();
                ClassDoc cd = pgmdoc.containingClass();

                writer.printSummaryLinkType(this, pgmdoc);
                if (cd != null && !(pgmdoc instanceof ConstructorDoc)
                               && !(pgmdoc instanceof ClassDoc)) {
                    // Add class context
                    writer.bold(cd.name() + ".");
                }
                writeSummaryLink(
                    pgmdoc instanceof ClassDoc ?
                        LinkInfoImpl.CONTEXT_CLASS_USE : LinkInfoImpl.CONTEXT_MEMBER,
                    cd, pgmdoc);
                writer.printSummaryLinkComment(this, pgmdoc);
            }
            writer.tableEnd();
            writer.space();
            writer.p();
        }
    }

    protected void navDetailLink(List members) {
            printNavDetailLink(members.size() > 0? true: false);
    }


    protected void navSummaryLink(List members,
            VisibleMemberMap visibleMemberMap) {
        if (members.size() > 0) {
            printNavSummaryLink(null, true);
            return;
        } else {
            ClassDoc icd = classdoc.superclass();
            while (icd != null) {
                List inhmembers = visibleMemberMap.getMembersFor(icd);
                if (inhmembers.size() > 0) {
                    printNavSummaryLink(icd, true);
                    return;
                }
                icd = icd.superclass();
            }
        }
        printNavSummaryLink(null, false);
    }

    protected void serialWarning(SourcePosition pos, String key, String a1, String a2) {
        if (configuration().serialwarn) {
            ConfigurationImpl.getInstance().getDocletSpecificMsg().warning(pos, key, a1, a2);
        }
    }

    public ProgramElementDoc[] eligibleMembers(ProgramElementDoc[] members) {
        return nodepr? Util.excludeDeprecatedMembers(members): members;
    }

    public ConfigurationImpl configuration() {
        return writer.configuration;
    }

    /**
     * {@inheritDoc}
     */
    public void writeMemberSummary(ClassDoc classDoc, ProgramElementDoc member,
        Tag[] firstSentenceTags, boolean isFirst, boolean isLast) {
        writer.printSummaryLinkType(this, member);
        writeSummaryLink(classDoc, member);
        writer.printSummaryLinkComment(this, member, firstSentenceTags);
    }
}
