// 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 "TextPackage.h"
#include "DFBuffer.h"
#include "DFString.h"
#include "DFFilesystem.h"
#include "DFCommon.h"
#include <stdlib.h>
#include <string.h>

////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                //
//                                           TextPackage                                          //
//                                                                                                //
////////////////////////////////////////////////////////////////////////////////////////////////////

static TextPackage *TextPackageNew(void)
{
    TextPackage *package = (TextPackage *)xcalloc(1,sizeof(TextPackage));
    package->retainCount = 1;
    package->items = DFHashTableNew((DFCopyFunction)xstrdup,free);
    package->keys = (char **)xcalloc(1,sizeof(char *));
    return package;
}

TextPackage *TextPackageRetain(TextPackage *package)
{
    if (package != NULL)
        package->retainCount++;
    return package;
}

void TextPackageRelease(TextPackage *package)
{
    if ((package == NULL) || (--package->retainCount > 0))
        return;

    for (size_t i = 0; i < package->nkeys; i++)
        free(package->keys[i]);
    free(package->keys);
    DFHashTableRelease(package->items);
    free(package);
}

static int processIncludes(TextPackage *package, const char *input, DFBuffer *output, const char *path, DFError **error)
{
    int ok = 1;
    const char **lines = DFStringSplit(input,"\n",0);
    for (int lineno = 0; lines[lineno] && ok; lineno++) {
        const char *line = lines[lineno];
        if (DFStringHasPrefix(line,"#include \"") && DFStringHasSuffix(line,"\"")) {
            char *inclRelPath = DFSubstring(line,10,strlen(line)-1);
            char *inclAbsPath = DFAppendPathComponent(path,inclRelPath);
            char *inclDirName = DFPathDirName(inclAbsPath);
            char *inclContent = DFStringReadFromFile(inclAbsPath,error);
            if (inclContent == NULL) {
                DFErrorFormat(error,"%s: %s",inclRelPath,DFErrorMessage(error));
                ok = 0;
            }
            else if (!processIncludes(package,inclContent,output,inclDirName,error)) {
                ok = 0;
            }
            free(inclRelPath);
            free(inclAbsPath);
            free(inclDirName);
            free(inclContent);
        }
        else {
            DFBufferFormat(output,"%s\n",line);
        }
    }
    free(lines);
    return ok;
}

static int parsePackage(TextPackage *package, const char *string, const char *path, DFError **error)
{
    DFBuffer *replaced = DFBufferNew();
    if (!strcmp(path,""))
        path = ".";

    if (!processIncludes(package,string,replaced,path,error)) {
        DFBufferRelease(replaced);
        return 0;
    }


    char *currentKey = xstrdup("");
    DFBuffer *currentValue = DFBufferNew();
    const char **lines = DFStringSplit(replaced->data,"\n",0);
    for (int lineno = 0; lines[lineno]; lineno++) {
        const char *line = lines[lineno];

        if (!DFStringHasPrefix(line,"#")) {
            DFBufferFormat(currentValue,"%s\n",line);
        }
        else if (DFStringHasPrefix(line,"#item ")) {
            package->keys = (char **)xrealloc(package->keys,(package->nkeys+2)*sizeof(char *));
            package->keys[package->nkeys++] = xstrdup(currentKey);
            package->keys[package->nkeys] = NULL;
            DFHashTableAdd(package->items,currentKey,currentValue->data);
            free(currentKey);
            DFBufferRelease(currentValue);
            currentKey = DFSubstring(line,6,strlen(line));
            currentValue = DFBufferNew();
        }
        else if (DFStringHasPrefix(line,"##")) {
            DFBufferFormat(currentValue,"%s\n",&line[1]);
        }
        else {
            DFErrorFormat(error,"Unknown command: %s on line %d",line,(lineno+1));
            return 0;
        }
    }
    package->keys = (char **)xrealloc(package->keys,(package->nkeys+2)*sizeof(char *));
    package->keys[package->nkeys++] = xstrdup(currentKey);
    package->keys[package->nkeys] = NULL;
    DFHashTableAdd(package->items,currentKey,currentValue->data);

    free(lines);
    free(currentKey);
    DFBufferRelease(currentValue);
    DFBufferRelease(replaced);
    return 1;
}

TextPackage *TextPackageNewWithFile(const char *filename, DFError **error)
{
    char *contents = DFStringReadFromFile(filename,error);
    if (contents == NULL) {
        DFErrorFormat(error,"%s: %s",filename,DFErrorMessage(error));
        return NULL;
    }

    char *path = DFPathDirName(filename);
    TextPackage *result = TextPackageNewWithString(contents,path,error);
    free(path);
    free(contents);
    return result;
}

TextPackage *TextPackageNewWithString(const char *string, const char *path, DFError **error)
{
    TextPackage *package = TextPackageNew();
    if (!parsePackage(package,string,path,error)) {
        TextPackageRelease(package);
        return NULL;
    }
    else
        return package;
}
