// 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 "DFBDT.h"
#include "DFDOM.h"
#include "DFXML.h"
#include "DFCommon.h"
#include "DFHashTable.h"
#include <assert.h>
#include <stdlib.h>

int nullIsVisible(void *ctx, DFNode *concrete)
{
    return 0;
}

DFNode *BDTContainerGet(void *ctx, DFLens *theLens, DFNode *abstract, DFNode *concrete)
{
    assert(abstract != NULL);
    if ((theLens->isVisible != NULL) && (theLens->get != NULL)) {
        for (DFNode *child = concrete->first; child != NULL; child = child->next) {
            DFNode *absChild = theLens->get(ctx,child);
            if (absChild != NULL)
                DFAppendChild(abstract,absChild);
        }
    }
    return abstract;
}

void BDTContainerPut(void *ctx, DFLens *theLens, DFNode *abstract, DFNode *concrete,
                     DFLookupConcreteFunction lookupConcrete)
{
    int (*isVisible)(void *ctx, DFNode *concrete) = (theLens->isVisible != NULL) ? theLens->isVisible : nullIsVisible;

    int count = 0;
    for (DFNode *abs = abstract->first; abs != NULL; abs = abs->next)
        count++;

    DFNode **conChildren = (DFNode **)xmalloc(count*sizeof(DFNode*));
    count = 0;

    for (DFNode *abs = abstract->first; abs != NULL; abs = abs->next) {
        DFNode *con = NULL;

        if (lookupConcrete != NULL)
            con = lookupConcrete(ctx,abs);

        if (con == NULL) {
            if (theLens->create != NULL)
                con = theLens->create(ctx,abs);
        }
        else {
            if (theLens->put != NULL)
                theLens->put(ctx,abs,con);
        }

        if (con != NULL)
            conChildren[count++] = con;
    }

    DFHashTable *oldPrevHidden = DFHashTableNew(NULL,NULL);
    for (int i = count-1; i >= 0; i--) {
        DFNode *con = conChildren[i];
        DFNode *prevHidden = con->prev;
        while ((prevHidden != NULL) && isVisible(ctx,prevHidden))
            prevHidden = prevHidden->prev;
        if (prevHidden != NULL) {
            DFHashTableAddInt(oldPrevHidden,con->seqNo,prevHidden);
        }
        else {
            DFHashTableAddInt(oldPrevHidden,con->seqNo,(void *)1);
        }
    }

    // Remove concrete nodes for which their abstract counterparts no longer exist
    DFHashTable *remaining = DFHashTableNew(NULL,NULL);
    for (int i = 0; i < count; i++)
        DFHashTableAddInt(remaining,conChildren[i]->seqNo,"");
    DFNode *next;
    for (DFNode *con = concrete->first; con != NULL; con = next) {
        next = con->next;
        if (isVisible(ctx,con)) {
            if (DFHashTableLookupInt(remaining,con->seqNo) == NULL) {
                if (theLens->remove != NULL)
                    theLens->remove(ctx,con);
                DFRemoveNode(con);
            }
        }
    }

    // Find the last node
    DFNode *last = NULL;
    if (concrete->last != NULL) {
        last = concrete->last;
        while ((last->prev != NULL) && !isVisible(ctx,last->prev))
            last = last->prev;
    }

    // Reinsert all the nodes in the correct order
    for (int i = count-1; i >= 0; i--) {
        DFNode *con = conChildren[i];

        DFNode *oldNext = con->next;
        while ((oldNext != NULL) && !isVisible(ctx,oldNext))
            oldNext = oldNext->next;

        DFNode *newNext = (i+1 < count) ? conChildren[i+1] : NULL;
        if (newNext == NULL)
            newNext = last;

        DFInsertBefore(concrete,con,newNext);
    }

    // Fixup stage - move nodes backwards as much as possible to their previous prevHidden
    for (DFNode *con = concrete->first; con != NULL; con = next) {
        next = con->next;
        if (!isVisible(ctx,con))
            continue;
        void *ph = DFHashTableLookupInt(oldPrevHidden,con->seqNo);
        if (ph == NULL)
            continue;
        if (ph == (void*)1)
            ph = NULL;;
        DFNode *prevHidden = (DFNode *)ph;
        if (prevHidden == NULL)
            continue;
        DFNode *insertionPoint = con->next;
        DFNode *actual = con->prev;
        int blockedByPrev = 0;
        int found = 0;
        for (;;) {
            if (!blockedByPrev) {
                if (actual == NULL)
                    insertionPoint = concrete->first;
                else
                    insertionPoint = actual->next;
            }
            if ((actual != NULL) && isVisible(ctx,actual))
                blockedByPrev = 1;
            if (actual == prevHidden) {
                found = 1;
                break;
            }
            if (actual == NULL) {
                break;
            }
            actual = actual->prev;
        }
        if (found)
            DFInsertBefore(concrete,con,insertionPoint);
    }

    free(conChildren);
    DFHashTableRelease(oldPrevHidden);
    DFHashTableRelease(remaining);
}
