/*
 * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package jdk.javadoc.internal.doclets.formats.html;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.TreeSet;

import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.IndexBuilder;


/**
 * Generate Separate Index Files for all the member names with Indexing in
 * Unicode Order. This will create "index-files" directory in the current or
 * destination directory and will generate separate file for each unicode index.
 *
 *  <p><b>This is NOT part of any supported API.
 *  If you write code that depends on this, you do so at your own risk.
 *  This code and its internal interfaces are subject to change or
 *  deletion without notice.</b>
 *
 * @see java.lang.Character
 */
public class SplitIndexWriter extends AbstractIndexWriter {

    private final List<Character> indexElements;

    /**
     * Construct the SplitIndexWriter. Uses path to this file and relative path
     * from this file.
     *
     * @param configuration the configuration for this doclet
     * @param path       Path to the file which is getting generated.
     * @param indexbuilder Unicode based Index from {@link IndexBuilder}
     * @param elements the collection of characters for which to generate index files
     */
    public SplitIndexWriter(HtmlConfiguration configuration,
                            DocPath path,
                            IndexBuilder indexbuilder,
                            Collection<Character> elements) {
        super(configuration, path, indexbuilder);
        this.indexElements = new ArrayList<>(elements);
    }

    /**
     * Generate separate index files, for each Unicode character, listing all
     * the members starting with the particular unicode character.
     *
     * @param configuration the configuration for this doclet
     * @param indexbuilder IndexBuilder built by {@link IndexBuilder}
     * @throws DocFileIOException if there is a problem generating the index files
     */
    public static void generate(HtmlConfiguration configuration,
                                IndexBuilder indexbuilder) throws DocFileIOException {
        DocPath path = DocPaths.INDEX_FILES;
        Set<Character> keys = new TreeSet<>(indexbuilder.getIndexMap().keySet());
        keys.addAll(configuration.tagSearchIndexKeys);
        ListIterator<Character> li = new ArrayList<>(keys).listIterator();
        int prev;
        int next;
        while (li.hasNext()) {
            prev = (li.hasPrevious()) ? li.previousIndex() + 1 : -1;
            Object ch = li.next();
            next = (li.hasNext()) ? li.nextIndex() + 1 : -1;
            DocPath filename = DocPaths.indexN(li.nextIndex());
            SplitIndexWriter indexgen = new SplitIndexWriter(configuration,
                    path.resolve(filename),
                    indexbuilder, keys);
            indexgen.generateIndexFile((Character) ch);
            if (!li.hasNext()) {
                indexgen.createSearchIndexFiles();
            }
        }
    }

    /**
     * Generate the contents of each index file, with Header, Footer,
     * Member Field, Method and Constructor Description.
     *
     * @param unicode Unicode character referring to the character for the
     * index.
     * @throws DocFileIOException if there is a problem generating an index file
     */
    protected void generateIndexFile(Character unicode) throws DocFileIOException {
        String title = resources.getText("doclet.Window_Split_Index",
                unicode.toString());
        HtmlTree body = getBody(getWindowTitle(title));
        Content headerContent = new ContentBuilder();
        addTop(headerContent);
        navBar.setUserHeader(getUserHeaderFooter(true));
        headerContent.add(navBar.getContent(true));
        Content main = new ContentBuilder();
        main.add(HtmlTree.DIV(HtmlStyle.header,
                HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING,
                        contents.getContent("doclet.Index"))));
        HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
        divTree.setStyle(HtmlStyle.contentContainer);
        addLinksForIndexes(divTree);
        if (configuration.tagSearchIndexMap.get(unicode) == null) {
            addContents(unicode, indexbuilder.getMemberList(unicode), divTree);
        } else if (indexbuilder.getMemberList(unicode) == null) {
            addSearchContents(unicode, configuration.tagSearchIndexMap.get(unicode), divTree);
        } else {
            addContents(unicode, indexbuilder.getMemberList(unicode),
                    configuration.tagSearchIndexMap.get(unicode), divTree);
        }
        addLinksForIndexes(divTree);
        main.add(divTree);
        HtmlTree footer = HtmlTree.FOOTER();
        navBar.setUserFooter(getUserHeaderFooter(false));
        footer.add(navBar.getContent(false));
        addBottom(footer);
        body.add(new BodyContents()
                .setHeader(headerContent)
                .addMainContent(main)
                .setFooter(footer)
                .toContent());
        String description = "index: " + unicode;
        printHtmlDocument(null, description, body);
    }

    /**
     * Add links for all the Index Files per unicode character.
     *
     * @param contentTree the content tree to which the links for indexes will be added
     */
    protected void addLinksForIndexes(Content contentTree) {
        for (int i = 0; i < indexElements.size(); i++) {
            int j = i + 1;
            contentTree.add(links.createLink(DocPaths.indexN(j),
                    new StringContent(indexElements.get(i).toString())));
            contentTree.add(Entity.NO_BREAK_SPACE);
        }
        contentTree.add(new HtmlTree(HtmlTag.BR));
        contentTree.add(links.createLink(pathToRoot.resolve(DocPaths.ALLCLASSES_INDEX),
                contents.allClassesLabel));
        if (!configuration.packages.isEmpty()) {
            contentTree.add(getVerticalSeparator());
            contentTree.add(links.createLink(pathToRoot.resolve(DocPaths.ALLPACKAGES_INDEX),
                    contents.allPackagesLabel));
        }
        if (!configuration.tagSearchIndex.isEmpty()) {
            contentTree.add(getVerticalSeparator());
            contentTree.add(links.createLink(pathToRoot.resolve(DocPaths.SYSTEM_PROPERTIES),
                    contents.systemPropertiesLabel));
        }
    }
}
