// 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 "DFChanges.h"
#include "DFHashTable.h"
#include "DFString.h"
#include "DFNameMap.h"
#include "DFCommon.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>

static char *fullNameForTag(DFDocument *doc, Tag tag)
{
    const TagDecl *tagDecl = DFNameMapNameForTag(doc->map,tag);
    const NamespaceDecl *nsDecl = DFNameMapNamespaceForID(doc->map,tagDecl->namespaceID);
    if ((nsDecl->prefix == NULL) || (tagDecl->namespaceID == NAMESPACE_HTML))
        return xstrdup(tagDecl->localName);
    else
        return DFFormatString("%s:%s",nsDecl->prefix,tagDecl->localName);
}

static void nodeDetailToBuffer(DFNode *node, DFBuffer *output)
{
    if (node == NULL) {
        DFBufferAppendString(output,"null");
        return;
    }
    switch (node->tag) {
        case DOM_DOCUMENT:
            DFBufferAppendString(output,"#document");
            break;
        case DOM_TEXT: {
            char *quotedValue = DFQuote(node->value);
            DFBufferAppendString(output,quotedValue);
            free(quotedValue);
            break;
        }
        case DOM_COMMENT:
            DFBufferAppendString(output,"#comment");
            break;
        case DOM_CDATA:
            DFBufferAppendString(output,"#cdata-section");
            break;
        case DOM_PROCESSING_INSTRUCTION:
            DFBufferAppendString(output,node->target);
            break;
        default: {
            char *elementName = fullNameForTag(node->doc,node->tag);
            DFBufferFormat(output,"<%s",elementName);
            for (unsigned int i = 0; i < node->attrsCount; i++) {
                char *attrName = fullNameForTag(node->doc,node->attrs[i].tag);
                const char *attrValue = node->attrs[i].value;
                char *quotedValue = DFQuote(attrValue);
                DFBufferFormat(output," %s=%s",attrName,quotedValue);
                free(quotedValue);
                free(attrName);
            }
            DFBufferFormat(output,">");
            switch (node->tag) {
                case WORD_T:
                case WORD_DELTEXT: {
                    char *content = DFNodeTextToString(node);
                    char *quoted = DFQuote(content);
                    char *sub;
                    if (strlen(quoted) >= 2)
                        sub = DFSubstring(quoted,1,strlen(quoted)-2);
                    else
                        sub = xstrdup(quoted);
                    DFBufferFormat(output,"%s</%s>",quoted,elementName);
                    free(sub);
                    free(quoted);
                    free(content);
                }
            }
            free(elementName);
            break;
        }
    }
}

static void DFElementsByAttr(DFNode *node, Tag attr, DFHashTable *result)
{
    if (node->tag >= MIN_ELEMENT_TAG) {
        const char *value = DFGetAttribute(node,attr);
        if ((value != NULL) && (DFHashTableLookup(result,value) == NULL))
            DFHashTableAdd(result,value,node);
    }

    for (DFNode *child = node->first; child != NULL; child = child->next)
        DFElementsByAttr(child,attr,result);
}

static void DFRecordChanges(DFNode *parent1, Tag idAttr, DFHashTable *map)
{
    assert(parent1->tag >= MIN_ELEMENT_TAG);

    // Check for changes in children
    for (DFNode *child1 = parent1->first; child1 != NULL; child1 = child1->next) {
        if (child1->tag >= MIN_ELEMENT_TAG)
            DFRecordChanges(child1,idAttr,map);
    }

    // Check the parent itself - starting with finding out, first of all, whether there
    // is actually a corresponding element in the new document
    const char *idValue = DFGetAttribute(parent1,idAttr);
    DFNode *parent2 = (idValue != NULL) ? DFHashTableLookup(map,idValue) : NULL;
    if (parent2 == NULL) {
        parent1->changed = 1;
        return;
    }

    if (parent1->tag != parent2->tag)
        parent1->changed = 1; // keep going - still want to check the children

    if (!identicalAttributesExcept(parent1,parent2,0))
        parent1->changed = 1;; // keep going - still want to check the children

    DFNode *child1 = parent1->first;
    DFNode *child2 = parent2->first;

    while ((child1 != NULL) && (child2 != NULL)) {

        // Non-element nodes can't be correlated based on their id attribute. So we judge whether
        // they are the same by inspecting their content, assuming the parent has the same set
        // of children.

        if (child1->tag != child2->tag) {
            parent1->changed = 1;
        }
        else {
            switch (child1->tag) {
                case DOM_TEXT:
                case DOM_COMMENT:
                case DOM_CDATA: {
                    assert(child1->value != NULL);
                    assert(child2->value != NULL);
                    if (strcmp(child1->value,child2->value))
                        child1->changed = 1;
                    break;
                }
                case DOM_PROCESSING_INSTRUCTION: {
                    if (strcmp(child1->target,child2->target) ||
                        strcmp(child1->value,child2->value)) {
                        child1->changed = 1;
                    }
                    break;
                }
            }
        }

        child1 = child1->next;
        child2 = child2->next;
    }

    if ((child1 != NULL) && (child2 == NULL))
        parent1->changed = 1;
    if ((child1 == NULL) && (child2 != NULL))
        parent1->changed = 1;
}

static void DFPropagateChanges(DFNode *node)
{
    for (DFNode *child = node->first; child != NULL; child = child->next) {
        DFPropagateChanges(child);
        if (child->changed || child->childrenChanged)
            node->childrenChanged = 1;
    }
}

static void DFChangesToStringRecursive(DFNode *node, int indent, DFBuffer *output)
{
    if (node->childrenChanged)
        DFBufferAppendString(output,"*");
    else
        DFBufferAppendString(output," ");

    if (node->changed)
        DFBufferAppendString(output,"C");
    else
        DFBufferAppendString(output," ");

    DFBufferAppendString(output,"  ");

    for (int i = 0; i < indent; i++)
        DFBufferAppendString(output,"    ");
    nodeDetailToBuffer(node,output);
    DFBufferAppendString(output,"\n");

    for (DFNode *child = node->first; child != NULL; child = child->next)
        DFChangesToStringRecursive(child,indent+1,output);
}

void DFComputeChanges(DFNode *root1, DFNode *root2, Tag idAttr)
{
    DFHashTable *map = DFHashTableNew(NULL,NULL);
    DFElementsByAttr(root2,idAttr,map);
    DFRecordChanges(root1,HTML_ID,map);
    DFPropagateChanges(root1);
    DFHashTableRelease(map);
}

char *DFChangesToString(DFNode *root)
{
    DFBuffer *output = DFBufferNew();
    DFChangesToStringRecursive(root,0,output);
    char *result = xstrdup(output->data);
    DFBufferRelease(output);
    return result;
}
