/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You 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.
==================================================================== */
package org.apache.poi.xssf.model;

import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.ss.util.CellAddress;
import org.apache.poi.util.Internal;
import org.apache.poi.xssf.usermodel.XSSFComment;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CommentsDocument;

@Internal
public class CommentsTable extends POIXMLDocumentPart {
    public static final String DEFAULT_AUTHOR = "";
    public static final int DEFAULT_AUTHOR_ID = 0;
    /**
     * Underlying XML Beans CTComment list.
     */
    private CTComments comments;
    /**
     * XML Beans uses a list, which is very slow
     *  to search, so we wrap things with our own
     *  map for fast lookup.
     */
    private Map<CellAddress, CTComment> commentRefs;

    public CommentsTable() {
        super();
        comments = CTComments.Factory.newInstance();
        comments.addNewCommentList();
        comments.addNewAuthors().addAuthor(DEFAULT_AUTHOR);
    }

    /**
     * @since POI 3.14-Beta1
     */
    public CommentsTable(PackagePart part) throws IOException {
        super(part);
        readFrom(part.getInputStream());
    }
    
    public void readFrom(InputStream is) throws IOException {
        try {
            CommentsDocument doc = CommentsDocument.Factory.parse(is, DEFAULT_XML_OPTIONS);
            comments = doc.getComments();
        } catch (XmlException e) {
            throw new IOException(e.getLocalizedMessage());
        }
    }
    public void writeTo(OutputStream out) throws IOException {
        CommentsDocument doc = CommentsDocument.Factory.newInstance();
        doc.setComments(comments);
        doc.save(out, DEFAULT_XML_OPTIONS);
    }

    @Override
    protected void commit() throws IOException {
        PackagePart part = getPackagePart();
        OutputStream out = part.getOutputStream();
        writeTo(out);
        out.close();
    }
    
    /**
     * Called after the reference is updated, so that
     *  we can reflect that in our cache
     *  @deprecated 2015-11-23 (circa POI 3.14beta1). Use {@link #referenceUpdated(CellAddress, CTComment)} instead
     */
    public void referenceUpdated(String oldReference, CTComment comment) {
       referenceUpdated(new CellAddress(oldReference), comment);
    }
    
    /**
     * Called after the reference is updated, so that
     *  we can reflect that in our cache
     *  @param oldReference the comment to remove from the commentRefs map
     *  @param comment the comment to replace in the commentRefs map
     */
    public void referenceUpdated(CellAddress oldReference, CTComment comment) {
       if(commentRefs != null) {
          commentRefs.remove(oldReference);
          commentRefs.put(new CellAddress(comment.getRef()), comment);
       }
    }

    public int getNumberOfComments() {
        return comments.getCommentList().sizeOfCommentArray();
    }

    public int getNumberOfAuthors() {
        return comments.getAuthors().sizeOfAuthorArray();
    }

    public String getAuthor(long authorId) {
        return comments.getAuthors().getAuthorArray((int)authorId);
    }

    public int findAuthor(String author) {
        String[] authorArray = comments.getAuthors().getAuthorArray();
        for (int i = 0 ; i < authorArray.length; i++) {
            if (authorArray[i].equals(author)) {
                return i;
            }
        }
        return addNewAuthor(author);
    }

    /**
     * Finds the cell comment at cellAddress, if one exists
     *
     * @param cellRef the address of the cell to find a comment
     * @return cell comment if one exists, otherwise returns null
     * @deprecated 2015-11-23 (circa POI 3.14beta1). Use {@link #findCellComment(CellAddress)} instead
     */
    public XSSFComment findCellComment(String cellRef) {
        return findCellComment(new CellAddress(cellRef));
    }

    /**
     * Finds the cell comment at cellAddress, if one exists
     *
     * @param cellAddress the address of the cell to find a comment
     * @return cell comment if one exists, otherwise returns null
     */
    public XSSFComment findCellComment(CellAddress cellAddress) {
        CTComment ct = getCTComment(cellAddress);
        return ct == null ? null : new XSSFComment(this, ct, null);
    }
    

    /**
     * Get the underlying CTComment xmlbean for a comment located at cellRef, if it exists
     *
     * @param ref the location of the cell comment
     * @return CTComment xmlbean if comment exists, otherwise return null.
     * @deprecated 2015-11-23 (circa POI 3.14beta1). Use {@link CommentsTable#getCTComment(CellAddress)} instead
     */
    @Internal
    public CTComment getCTComment(String ref) {
        return getCTComment(new CellAddress(ref));
    }
    
    /**
     * Get the underlying CTComment xmlbean for a comment located at cellRef, if it exists
     *
     * @param cellRef the location of the cell comment
     * @return CTComment xmlbean if comment exists, otherwise return null.
     */
    @Internal
    public CTComment getCTComment(CellAddress cellRef) {
        // Create the cache if needed
        prepareCTCommentCache();

        // Return the comment, or null if not known
        return commentRefs.get(cellRef);
    }
    
    /**
     * Returns all cell comments on this sheet.
     * @return A map of each Comment in this sheet, keyed on the cell address where
     * the comment is located.
     */
    public Map<CellAddress, XSSFComment> getCellComments() {
        prepareCTCommentCache();
        final TreeMap<CellAddress, XSSFComment> map = new TreeMap<CellAddress, XSSFComment>();
        
        for (final Entry<CellAddress, CTComment> e: commentRefs.entrySet()) {
            map.put(e.getKey(), new XSSFComment(this, e.getValue(), null));
        }
        
        return map;
    }

    /**
     * Refresh Map<CellAddress, CTComment> commentRefs cache,
     * Calls that use the commentRefs cache will perform in O(1)
     * time rather than O(n) lookup time for List<CTComment> comments.
     */
    private void prepareCTCommentCache() {
        // Create the cache if needed
        if(commentRefs == null) {
           commentRefs = new HashMap<CellAddress, CTComment>();
           for (CTComment comment : comments.getCommentList().getCommentArray()) {
              commentRefs.put(new CellAddress(comment.getRef()), comment);
           }
        }
    }
    
    /**
     * Create a new comment located at cell address
     *
     * @param ref the location to add the comment
     * @return a new CTComment located at ref with default author
     * @deprecated 2015-11-23 (circa POI 3.14beta1). Use {@link #newComment(CellAddress)} instead
     */
    @Internal
    public CTComment newComment(String ref) {
        return newComment(new CellAddress(ref));
    }
    
    /**
     * Create a new comment located` at cell address
     *
     * @param ref the location to add the comment
     * @return a new CTComment located at ref with default author
     */
    @Internal
    public CTComment newComment(CellAddress ref) {
        CTComment ct = comments.getCommentList().addNewComment();
        ct.setRef(ref.formatAsString());
        ct.setAuthorId(DEFAULT_AUTHOR_ID);
        
        if(commentRefs != null) {
           commentRefs.put(ref, ct);
        }
        return ct;
    }
    
    /**
     * Remove the comment at cellRef location, if one exists
     *
     * @param cellRef the location of the comment to remove
     * @return returns true if a comment was removed
     * @deprecated 2015-11-23 (circa POI 3.14beta1). Use {@link #removeComment(CellAddress)} instead
     */
    public boolean removeComment(String cellRef) {
        return removeComment(new CellAddress(cellRef));
    }

    /**
     * Remove the comment at cellRef location, if one exists
     *
     * @param cellRef the location of the comment to remove
     * @return returns true if a comment was removed
     */
    public boolean removeComment(CellAddress cellRef) {
        final String stringRef = cellRef.formatAsString();
        CTCommentList lst = comments.getCommentList();
        if(lst != null) {
            CTComment[] commentArray = lst.getCommentArray();
            for (int i = 0; i < commentArray.length; i++) {
                CTComment comment = commentArray[i];
                if (stringRef.equals(comment.getRef())) {
                    lst.removeComment(i);

                    if(commentRefs != null) {
                       commentRefs.remove(cellRef);
                    }
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Add a new author to the CommentsTable.
     * This does not check if the author already exists.
     *
     * @param author the name of the comment author
     * @return the index of the new author
     */
    private int addNewAuthor(String author) {
        int index = comments.getAuthors().sizeOfAuthorArray();
        comments.getAuthors().insertAuthor(index, author);
        return index;
    }

    /**
     * Returns the underlying CTComments list xmlbean
     *
     * @return underlying comments list xmlbean
     */
    @Internal
    public CTComments getCTComments(){
        return comments;
    }
}
