/*
 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.sun.imageio.plugins.tiff;

import java.util.Arrays;
import java.util.List;
import javax.imageio.metadata.IIOMetadataNode;
import org.w3c.dom.Node;
import javax.imageio.plugins.tiff.TIFFDirectory;
import javax.imageio.plugins.tiff.TIFFField;
import javax.imageio.plugins.tiff.TIFFTag;
import javax.imageio.plugins.tiff.TIFFTagSet;

/**
 * The {@code Node} representation of a {@code TIFFField}
 * wherein the child node is procedural rather than buffered.
 */
public class TIFFFieldNode extends IIOMetadataNode {
    private static boolean isIFD(TIFFField f) {
        int type = f.getType();
        return f.hasDirectory() &&
            (type == TIFFTag.TIFF_LONG || type == TIFFTag.TIFF_IFD_POINTER);
    }

    private static String getNodeName(TIFFField f) {
        return isIFD(f) ? "TIFFIFD" : "TIFFField";
    }

    private boolean isIFD;

    private Boolean isInitialized = Boolean.FALSE;

    private TIFFField field;

    public TIFFFieldNode(TIFFField field) {
        super(getNodeName(field));

        isIFD = isIFD(field);

        this.field = field;

        TIFFTag tag = field.getTag();
        int tagNumber = tag.getNumber();
        String tagName = tag.getName();

        if(isIFD) {
            if(tagNumber != 0) {
                setAttribute("parentTagNumber", Integer.toString(tagNumber));
            }
            if(tagName != null) {
                setAttribute("parentTagName", tagName);
            }

            TIFFDirectory dir = field.hasDirectory() ?
                field.getDirectory() : (TIFFDirectory)field.getData();
            TIFFTagSet[] tagSets = dir.getTagSets();
            if(tagSets != null) {
                StringBuilder tagSetNames = new StringBuilder();
                for(int i = 0; i < tagSets.length; i++) {
                    tagSetNames.append(tagSets[i].getClass().getName());
                    if(i != tagSets.length - 1) {
                        tagSetNames.append(",");
                    }
                }
                setAttribute("tagSets", tagSetNames.toString());
            }
        } else {
            setAttribute("number", Integer.toString(tagNumber));
            setAttribute("name", tagName);
        }
    }

    private synchronized void initialize() {
        if(isInitialized) return;

        if(isIFD) {
            TIFFDirectory dir = field.hasDirectory() ?
                field.getDirectory() : (TIFFDirectory)field.getData();
            TIFFField[] fields = dir.getTIFFFields();
            if(fields != null) {
                TIFFTagSet[] tagSets = dir.getTagSets();
                List<TIFFTagSet> tagSetList = Arrays.asList(tagSets);
                int numFields = fields.length;
                for(int i = 0; i < numFields; i++) {
                    TIFFField f = fields[i];
                    int tagNumber = f.getTagNumber();
                    TIFFTag tag = TIFFIFD.getTag(tagNumber, tagSetList);

                    Node node = f.getAsNativeNode();

                    if (node != null) {
                        appendChild(node);
                    }
                }
            }
        } else {
            IIOMetadataNode child;
            int count = field.getCount();
            if (field.getType() == TIFFTag.TIFF_UNDEFINED) {
                child = new IIOMetadataNode("TIFFUndefined");

                byte[] data = field.getAsBytes();
                StringBuffer sb = new StringBuffer();
                for (int i = 0; i < count; i++) {
                    sb.append(Integer.toString(data[i] & 0xff));
                    if (i < count - 1) {
                        sb.append(",");
                    }
                }
                child.setAttribute("value", sb.toString());
            } else {
                child = new IIOMetadataNode("TIFF" +
                                            TIFFField.getTypeName(field.getType()) +
                                            "s");

                TIFFTag tag = field.getTag();

                for (int i = 0; i < count; i++) {
                    IIOMetadataNode cchild =
                        new IIOMetadataNode("TIFF" +
                                            TIFFField.getTypeName(field.getType()));

                    cchild.setAttribute("value", field.getValueAsString(i));
                    if (tag.hasValueNames() && field.isIntegral()) {
                        int value = field.getAsInt(i);
                        String name = tag.getValueName(value);
                        if (name != null) {
                            cchild.setAttribute("description", name);
                        }
                    }

                    child.appendChild(cchild);
                }
            }
            appendChild(child);
        }

        isInitialized = Boolean.TRUE;
    }

    // Need to override this method to avoid a stack overflow exception
    // which will occur if super.appendChild is called from initialize().
    public Node appendChild(Node newChild) {
        if (newChild == null) {
            throw new NullPointerException("newChild == null!");
        }

        return super.insertBefore(newChild, null);
    }

    // Override all methods which refer to child nodes.

    public boolean hasChildNodes() {
        initialize();
        return super.hasChildNodes();
    }

    public int getLength() {
        initialize();
        return super.getLength();
    }

    public Node getFirstChild() {
        initialize();
        return super.getFirstChild();
    }

    public Node getLastChild() {
        initialize();
        return super.getLastChild();
    }

    public Node getPreviousSibling() {
        initialize();
        return super.getPreviousSibling();
    }

    public Node getNextSibling() {
        initialize();
        return super.getNextSibling();
    }

    public Node insertBefore(Node newChild,
                             Node refChild) {
        initialize();
        return super.insertBefore(newChild, refChild);
    }

    public Node replaceChild(Node newChild,
                             Node oldChild) {
        initialize();
        return super.replaceChild(newChild, oldChild);
    }

    public Node removeChild(Node oldChild) {
        initialize();
        return super.removeChild(oldChild);
    }

    public Node cloneNode(boolean deep) {
        initialize();
        return super.cloneNode(deep);
    }
}
