/*
 * 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;
}

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;
}
