/*
 * 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.fop.render.pdf.pdfbox;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSInteger;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSObject;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDNumberTreeNode;
import org.apache.pdfbox.pdmodel.graphics.PDXObject;

public class PageParentTreeFinder {

    private PDPage srcPage;
    public PageParentTreeFinder(PDPage srcPage) {
        this.srcPage = srcPage;
    }

    public COSArray getPageParentTreeArray(PDDocument srcDoc) throws IOException {
        int position = srcPage.getCOSObject().getInt(COSName.STRUCT_PARENTS);
        if (position == -1) {
            position = findXObjectStructParent();
        }
        if (position != -1) {
            PDNumberTreeNode srcNumberTreeNode = srcDoc.getDocumentCatalog().getStructureTreeRoot().getParentTree();
            return traverseParentTree(srcNumberTreeNode.getCOSObject(), position);
        }
        return new COSArray();
    }
    //TODO handle structural hierarchy in xboject stream
    private int findXObjectStructParent() throws IOException {
        int position = -1;
        Iterable<COSName> mapXObject = srcPage.getResources().getXObjectNames();
        for (COSName n : mapXObject) {
            PDXObject t = srcPage.getResources().getXObject(n);
            COSDictionary xObjectDict = t.getCOSObject();
            position = xObjectDict.getInt(COSName.STRUCT_PARENTS);
            if (position != -1) {
                return position;
            }
        }
        return position;
    }

    private COSArray traverseParentTree(COSDictionary numberTreeNodeDict, int position) {
        COSArray numberTree;
        COSArray parentTree;
        List<COSArray> nums = new ArrayList<COSArray>();
        if (numberTreeNodeDict.containsKey(COSName.NUMS)) {
            numberTree = (COSArray)numberTreeNodeDict.getItem(COSName.NUMS);
            return extractMarkedContentParents(numberTree, position);
        } else {
            parentTree = (COSArray) numberTreeNodeDict.getDictionaryObject(COSName.KIDS);
            traverseKids(parentTree, position, nums);
        }
        if (nums.isEmpty()) {
            return new COSArray();
        }
        return nums.get(0);
    }

    private void traverseKids(COSBase kids, int position, List<COSArray> numList) {
        if (!numList.isEmpty()) {
            return;
        }
        if (kids instanceof COSArray) {
            COSArray kidsArray = (COSArray)kids;
            for (COSBase kid : kidsArray) {
                COSObject kidCOSObj = (COSObject) kid;
                traverseKids(kidCOSObj, position, numList);
            }
        } else if (kids instanceof COSObject) {
            COSObject kidCOSObj = (COSObject) kids;
            if (kidCOSObj.getDictionaryObject(COSName.NUMS) == null) {
                traverseKids(kidCOSObj.getDictionaryObject(COSName.KIDS), position, numList);
            } else {
                if (kidCOSObj.getDictionaryObject(COSName.LIMITS) != null) {
                    COSArray kidCOSArray = (COSArray) kidCOSObj.getDictionaryObject(COSName.LIMITS);
                    int lowerLimit = ((COSInteger) kidCOSArray.get(0)).intValue();
                    int upperLimit = ((COSInteger) kidCOSArray.get(1)).intValue();
                    if (lowerLimit <= position && position <= upperLimit) {
                        COSArray nums = (COSArray) kidCOSObj.getDictionaryObject(COSName.NUMS);
                        numList.add(extractMarkedContentParents(nums, position));
                    }
                } else {
                    COSArray nums = (COSArray) kidCOSObj.getDictionaryObject(COSName.NUMS);
                    numList.add(extractMarkedContentParents(nums, position));
                }
            }
        }
    }

    private COSArray extractMarkedContentParents(COSArray numberTree, int position) {
        COSBase tempObject;
        boolean keyFlag = false;
        for (COSBase kid : numberTree) {
            if (keyFlag) {
                if (kid instanceof COSObject) {
                    tempObject = ((COSObject)kid).getObject();
                    return (COSArray)tempObject;
                } else if (kid instanceof COSArray) {
                    return (COSArray)kid;
                }
            }
            if (kid instanceof COSInteger) {
                int temp = ((COSInteger)kid).intValue();
                if (temp == position) {
                    keyFlag = true;
                }
            }
        }
        return new COSArray();
    }
}
