// 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.

#include "DFPlatform.h"
#include "DFMarkupCompatibility.h"
#include "DFNameMap.h"
#include "DFString.h"
#include "DFCommon.h"
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_DEPTH 256

////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                //
//                                      DFMarkupCompatibility                                     //
//                                                                                                //
////////////////////////////////////////////////////////////////////////////////////////////////////

typedef struct MCDecl {
    NamespaceID nsId;
    Tag tag;
    MCAction action;
} MCDecl;

typedef struct MCRecord {
    MCDecl *decls;
    int count;
    int alloc;
    DFHashTable *namespaces;
} MCRecord;

struct MCStack {
    MCRecord records[MAX_DEPTH];
    int depth;
};

struct DFMarkupCompatibility {
    MCRecord records[MAX_DEPTH];
    int depth;
};

DFMarkupCompatibility *DFMarkupCompatibilityNew(void)
{
    DFMarkupCompatibility *mc = (DFMarkupCompatibility *)xcalloc(1,sizeof(DFMarkupCompatibility));
    return mc;
}

void DFMarkupCompatibilityFree(DFMarkupCompatibility *mc)
{
    while (mc->depth > 0)
        DFMarkupCompatibilityPop(mc);
    free(mc);
}

static void addDeclToRecord(MCRecord *record, NamespaceID nsId, Tag tag, MCAction action)
{
    record->count++;
    record->decls = (MCDecl *)xrealloc(record->decls,record->count*sizeof(MCDecl));
    record->decls[record->count-1].nsId = nsId;
    record->decls[record->count-1].tag = tag;
    record->decls[record->count-1].action = action;
}

void DFMarkupCompatibilityPush(DFMarkupCompatibility *mc, int nb_namespaces, const char **namespaces, DFNameMap *map)
{
    mc->depth++;
    if (mc->depth < MAX_DEPTH) {
        MCRecord *record = &mc->records[mc->depth-1];
        bzero(record,sizeof(MCRecord));
        if (nb_namespaces > 0) {
            record->namespaces = DFHashTableNew((DFCopyFunction)xstrdup,(DFFreeFunction)free);
            for (int i = 0; i < nb_namespaces; i++) {
                const char *nsPrefix = namespaces[i*2];
                const char *nsURI = namespaces[i*2+1];
                NamespaceID nsId = DFNameMapFoundNamespace(map,nsURI,nsPrefix);
                char nsIdStr[20];
                snprintf(nsIdStr,20,"%u",nsId);
                const char *prefix = "";
                if (nsPrefix != NULL)
                    prefix = (const char *)nsPrefix;
                DFHashTableAdd(record->namespaces,prefix,nsIdStr);
            }
        }
    }
}

void DFMarkupCompatibilityPop(DFMarkupCompatibility *mc)
{
    assert(mc->depth > 0);
    if (mc->depth < MAX_DEPTH) {
        MCRecord *record = &mc->records[mc->depth-1];
        free(record->decls);
        DFHashTableRelease(record->namespaces);
    }
    mc->depth--;
}

MCAction DFMarkupCompatibilityLookup(DFMarkupCompatibility *mc, NamespaceID nsId, Tag tag, int isElement)
{
    MCAction action = MCActionDefault;
    for (int recordIndex = mc->depth-1; recordIndex >= 0; recordIndex--) {
        MCRecord *record = &mc->records[recordIndex];
        for (int declIndex = 0; declIndex < record->count; declIndex++) {
            MCDecl *decl = &record->decls[declIndex];
            if (decl->nsId == nsId) {
                switch (decl->action) {
                    case MCActionIgnore:
                        return MCActionIgnore;
                    case MCActionProcessContent:
                        if ((decl->tag == 0) || ((decl->tag == tag) && isElement))
                            return MCActionProcessContent;
                        break;
                    case MCActionMustUnderstand:
                        return MCActionMustUnderstand;
                    default:
                        break;
                }
            }
        }
    }
    return action;
}

// FIXME: Not covered by tests
void DFMarkupCompatibilityProcessAttr(DFMarkupCompatibility *mc, Tag attr, const char *value, DFNameMap *map)
{
    const char **tokens = DFStringTokenize(value,isspace);
    for (int tokIndex = 0; tokens[tokIndex]; tokIndex++) {
        const char *component = tokens[tokIndex];

        char *prefix = NULL;
        char *localName = NULL;
        const char *colon = strchr(component,':');
        if (colon != NULL) {
            size_t colonPos = colon - component;
            prefix = DFSubstring(component,0,colonPos);
            localName = DFSubstring(component,colonPos+1,strlen(component));
        }
        else {
            prefix = xstrdup(component);
            localName = NULL;
        }

        const char *nsIdStr = NULL;

        // Find namespace ID for prefix
        for (int recordIndex = mc->depth-1; recordIndex >= 0; recordIndex--) {
            MCRecord *record = &mc->records[recordIndex];
            if (record->namespaces != NULL)
                nsIdStr = DFHashTableLookup(record->namespaces,prefix);
        }

        if (nsIdStr != NULL) {

            NamespaceID nsId = atoi(nsIdStr);
            Tag tag = 0;

            const NamespaceDecl *nsDecl = DFNameMapNamespaceForID(map,nsId);

            if (localName != NULL)
                tag = DFNameMapTagForName(map,nsDecl->namespaceURI,localName);

            switch (attr) {
                case MC_IGNORABLE:
                    addDeclToRecord(&mc->records[mc->depth-1],nsId,tag,MCActionIgnore);
                    break;
                case MC_PROCESSCONTENT:
                    addDeclToRecord(&mc->records[mc->depth-1],nsId,tag,MCActionProcessContent);
                    break;
                case MC_MUSTUNDERSTAND:
                    addDeclToRecord(&mc->records[mc->depth-1],nsId,tag,MCActionMustUnderstand);
                    break;
            }
        }
        free(prefix);
        free(localName);
    }
    free(tokens);
}
