// 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 "WordObjects.h"
#include "WordPackage.h"
#include "WordDrawing.h"
#include "WordBookmark.h"
#include "WordCaption.h"
#include "DFDOM.h"
#include "DFString.h"
#include "DFHashTable.h"
#include "DFCommon.h"
#include "DFPlatform.h"
#include <assert.h>
#include <stdlib.h>

////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                //
//                                           WordObjects                                          //
//                                                                                                //
////////////////////////////////////////////////////////////////////////////////////////////////////

struct WordObjects {
    WordPackage *package;
    DFHashTable *drawingsById;
    DFHashTable *bookmarksById;
    DFHashTable *bookmarksByName;
    DFHashTable *captionsByTarget;
    int nextDrawingId;
    int nextBookmarkNameNum;
    int nextBookmarkId;
};

WordObjects *WordObjectsNew(WordPackage *package)
{
    WordObjects *objects = (WordObjects *)xcalloc(1,sizeof(WordObjects));
    objects->package = WordPackageRetain(package);
    objects->drawingsById = DFHashTableNew((DFCopyFunction)WordDrawingRetain,(DFFreeFunction)WordDrawingRelease);
    objects->bookmarksById = DFHashTableNew((DFCopyFunction)WordBookmarkRetain,(DFFreeFunction)WordBookmarkRelease);
    objects->bookmarksByName = DFHashTableNew((DFCopyFunction)WordBookmarkRetain,(DFFreeFunction)WordBookmarkRelease);
    objects->captionsByTarget = DFHashTableNew((DFCopyFunction)WordCaptionRetain,(DFFreeFunction)WordCaptionRelease);
    objects->nextDrawingId = 1;
    objects->nextBookmarkNameNum = 0;
    objects->nextBookmarkId = 0;
    return objects;
}

void WordObjectsFree(WordObjects *objects)
{
    DFHashTableRelease(objects->drawingsById);
    DFHashTableRelease(objects->bookmarksById);
    DFHashTableRelease(objects->bookmarksByName);
    DFHashTableRelease(objects->captionsByTarget);
    WordPackageRelease(objects->package);
    free(objects);
}

static void scanRecursive(WordObjects *objects, DFNode *node)
{
    switch (node->tag) {
        case WORD_BOOKMARK: {
            const char *bookmarkId = DFGetAttribute(node,WORD_ID);
            const char *bookmarkName = DFGetAttribute(node,WORD_NAME);
            if ((bookmarkId == NULL) ||
                (bookmarkName == NULL) ||
                (WordObjectsBookmarkWithId(objects,bookmarkId) != NULL) ||
                (WordObjectsBookmarkWithName(objects,bookmarkName) != NULL)) {
                DFRemoveNode(node);
                return;
            }
            WordBookmark *bookmark = WordObjectsAddBookmarkWithId(objects,bookmarkId,bookmarkName);
            bookmark->element = node;
            break;
        }
        case DML_WP_DOCPR: {
            const char *drawingId = DFGetAttribute(node,NULL_ID);
            if ((drawingId != NULL) && (WordObjectsDrawingWithId(objects,drawingId) == NULL))
                WordObjectsAddDrawingWithId(objects,drawingId);
            break;
        }
    }

    DFNode *next;
    for (DFNode *child = node->first; child != NULL; child = next) {
        next = child->next;
        scanRecursive(objects,child);
    }
}

void WordObjectsScan(WordObjects *objects)
{
    scanRecursive(objects,objects->package->document->docNode);
}

WordDrawing *WordObjectsDrawingWithId(WordObjects *objects, const char *drawingId)
{
    return DFHashTableLookup(objects->drawingsById,drawingId);
}

WordDrawing *WordObjectsAddDrawingWithId(WordObjects *objects, const char *drawingId)
{
    WordDrawing *drawing = WordDrawingNew(drawingId);
    DFHashTableAdd(objects->drawingsById,drawingId,drawing);
    WordDrawingRelease(drawing);
    return drawing;
}

static char *createDrawingId(WordObjects *objects)
{
    while (1) {
        char *idStr = DFFormatString("%d",objects->nextDrawingId);
        if (DFHashTableLookup(objects->drawingsById,idStr) == NULL)
            return idStr;
        objects->nextDrawingId++;
        free(idStr);
    }
}

WordDrawing *WordObjectsAddDrawing(WordObjects *objects)
{
    char *drawingId = createDrawingId(objects);
    WordDrawing *drawing = WordObjectsAddDrawingWithId(objects,drawingId);
    free(drawingId);
    return drawing;
}

struct WordBookmark *WordObjectsBookmarkWithId(WordObjects *objects, const char *bookmarkId)
{
    return DFHashTableLookup(objects->bookmarksById,bookmarkId);
}

struct WordBookmark *WordObjectsBookmarkWithName(WordObjects *objects, const char *bookmarkName)
{
    return DFHashTableLookup(objects->bookmarksByName,bookmarkName);
}

struct WordBookmark *WordObjectsAddBookmarkWithId(WordObjects *objects, const char *bookmarkId, const char *bookmarkName)
{
    WordBookmark *bookmark = WordBookmarkNew(bookmarkId,bookmarkName);
    DFHashTableAdd(objects->bookmarksById,bookmarkId,bookmark);
    DFHashTableAdd(objects->bookmarksByName,bookmarkName,bookmark);
    WordBookmarkRelease(bookmark);
    return bookmark;
}

static char *createBookmarkName(WordObjects *objects)
{
    while (1) {
        char *nameStr = DFFormatString("uxwrite%d",objects->nextBookmarkNameNum);
        if (DFHashTableLookup(objects->bookmarksByName,nameStr) == NULL)
            return nameStr;
        objects->nextBookmarkNameNum++;
        free(nameStr);
    }
}

static char *createBookmarkId(WordObjects *objects)
{
    while (1) {
        char *idStr = DFFormatString("%d",objects->nextBookmarkId);
        if (DFHashTableLookup(objects->bookmarksById,idStr) == NULL)
            return idStr;
        objects->nextBookmarkId++;
        free(idStr);
    }
}

struct WordBookmark *WordObjectsAddBookmark(WordObjects *objects)
{
    char *bookmarkId = createBookmarkId(objects);
    char *bookmarkName = createBookmarkName(objects);
    WordBookmark *bookmark = WordObjectsAddBookmarkWithId(objects,bookmarkId,bookmarkName);
    free(bookmarkId);
    free(bookmarkName);
    return bookmark;
}

void WordObjectsCollapseBookmarks(WordObjects *objects)
{
    WordBookmarks_collapseNew(objects->package->document);
}

void WordObjectsAnalyzeBookmarks(WordObjects *objects, WordSheet *sheet)
{
    const char **keys = DFHashTableCopyKeys(objects->bookmarksById);
    for (int i = 0; keys[i]; i++) {
        WordBookmark *bookmark = DFHashTableLookup(objects->bookmarksById,keys[i]);
        WordBookmarkAnalyze(bookmark,sheet);
    }
    free(keys);
}

void WordObjectsExpandBookmarks(WordObjects *objects)
{
    WordBookmarks_expandNew(objects->package->document);
}

struct WordCaption *WordObjectsCaptionForTarget(WordObjects *objects, DFNode *target)
{
    assert((target->tag == HTML_TABLE) || (target->tag == HTML_FIGURE));
    return DFHashTableLookupInt(objects->captionsByTarget,target->seqNo);
}

void WordObjectsSetCaption(WordObjects *objects, struct WordCaption *caption, DFNode *target)
{
    assert((target->tag == HTML_TABLE) || (target->tag == HTML_FIGURE));
    DFHashTableAddInt(objects->captionsByTarget,target->seqNo,caption);
}
