/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkPDFResourceDict.h"
#include "SkPostConfig.h"

// Sanity check that the values of enum SkPDFResourceType correspond to the
// expected values as defined in the arrays below.
// If these are failing, you may need to update the resource_type_prefixes
// and resource_type_names arrays below.
SK_COMPILE_ASSERT(SkPDFResourceDict::kExtGState_ResourceType == 0,
                  resource_type_mismatch);
SK_COMPILE_ASSERT(SkPDFResourceDict::kPattern_ResourceType == 1,
                  resource_type_mismatch);
SK_COMPILE_ASSERT(SkPDFResourceDict::kXObject_ResourceType == 2,
                  resource_type_mismatch);
SK_COMPILE_ASSERT(SkPDFResourceDict::kFont_ResourceType == 3,
                  resource_type_mismatch);

static const char resource_type_prefixes[] = {
        'G',
        'P',
        'X',
        'F'
};

static const char* resource_type_names[] = {
        "ExtGState",
        "Pattern",
        "XObject",
        "Font"
};

static char get_resource_type_prefix(
        SkPDFResourceDict::SkPDFResourceType type) {
    SkASSERT(type >= 0);
    SkASSERT(type < SkPDFResourceDict::kResourceTypeCount);

    return resource_type_prefixes[type];
}

static const char* get_resource_type_name(
        SkPDFResourceDict::SkPDFResourceType type) {
    SkASSERT(type >= 0);
    SkASSERT(type < SkPDFResourceDict::kResourceTypeCount);

    return resource_type_names[type];
}

SkPDFResourceDict::SkPDFResourceDict() : SkPDFDict() {
    const char procs[][7] = {"PDF", "Text", "ImageB", "ImageC", "ImageI"};
    SkPDFArray* procSets = SkNEW(SkPDFArray());

    procSets->reserve(SK_ARRAY_COUNT(procs));
    for (size_t i = 0; i < SK_ARRAY_COUNT(procs); i++) {
        procSets->appendName(procs[i]);
    }
    insert("ProcSets", procSets)->unref();

    // Actual sub-dicts will be lazily added later
    fTypes.setCount(kResourceTypeCount);
    for (int i=0; i < kResourceTypeCount; i++) {
        fTypes[i] = NULL;
    }
}

SkPDFObject* SkPDFResourceDict::insertResourceAsReference(
        SkPDFResourceType type, int key, SkPDFObject* value) {
    SkAutoTUnref<SkPDFObjRef> ref(SkNEW_ARGS(SkPDFObjRef, (value)));
    insertResource(type, key, ref);
    fResources.add(value);

    return value;
}

void SkPDFResourceDict::getReferencedResources(
        const SkTSet<SkPDFObject*>& knownResourceObjects,
        SkTSet<SkPDFObject*>* newResourceObjects,
        bool recursive) const {
    // TODO: reserve not correct if we need to recursively explore.
    newResourceObjects->setReserve(newResourceObjects->count() +
                                   fResources.count());

    for (int i = 0; i < fResources.count(); i++) {
        if (!knownResourceObjects.contains(fResources[i]) &&
                !newResourceObjects->contains(fResources[i])) {
            newResourceObjects->add(fResources[i]);
            fResources[i]->ref();
            if (recursive) {
                fResources[i]->getResources(knownResourceObjects,
                                            newResourceObjects);
            }
        }
    }
}

SkString SkPDFResourceDict::getResourceName(
        SkPDFResourceType type, int key) {
    SkString keyString;
    keyString.printf("%c%d", get_resource_type_prefix(type), key);
    return keyString;
}

SkPDFObject* SkPDFResourceDict::insertResource(
        SkPDFResourceType type, int key, SkPDFObject* value) {
    SkPDFDict* typeDict = fTypes[type];
    if (NULL == typeDict) {
        SkAutoTUnref<SkPDFDict> newDict(SkNEW(SkPDFDict()));
        SkAutoTUnref<SkPDFName> typeName(
                SkNEW_ARGS(SkPDFName, (get_resource_type_name(type))));
        insert(typeName, newDict);  // ref counting handled here
        fTypes[type] = newDict;
        typeDict = newDict.get();
    }

    SkAutoTUnref<SkPDFName> keyName(
            SkNEW_ARGS(SkPDFName, (getResourceName(type, key))));
    typeDict->insert(keyName, value);
    return value;
}
