/* Copyright (C) 2014 InfiniDB, Inc.
   Copyright (C) 2016 MariaDB Corporation

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; version 2 of
   the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
   MA 02110-1301, USA. */

/***********************************************************************
 *   $Id: dmlparser.cpp 9210 2013-01-21 14:10:42Z rdempsey $
 *
 *
 ***********************************************************************/
#include <fstream>
#include <errno.h>

#include "dmlparser.h"

#undef DECIMAL
#undef DELETE
#undef IN
#ifdef _MSC_VER
#include "dml-gram-win.h"
#else
#include "dml-gram.h"
#endif

#include <stdio.h>
#include <string.h>

int dmllex_init_extra(void* user_defined, void** yyscanner);
int dmllex_destroy(void* yyscanner);
int dmlparse(void* yyscanner);

namespace dmlpackage
{
using namespace std;

void scanner_finish(void* yyscanner);
void scanner_init(const char* str, void* yyscanner);
void grammar_init(dmlpackage::ParseTree* _ptree, bool);
valbuf_t get_valbuffer(void);

void free_copybuffer();
void set_defaultSchema(std::string schema);

DMLParser::DMLParser() :
    fStatus(-1), fDebug(false)
{}

DMLParser::~DMLParser()
{
    scanner_finish(scanner);
    dmllex_destroy(scanner);
}

void DMLParser::setDebug(bool debug)
{
    fDebug = true;
}

int DMLParser::parse(const char* dmltext)
{
    dmllex_init_extra(&scanData, &scanner);
    scanner_init(dmltext, scanner);
    grammar_init(&fParseTree, fDebug);
    fStatus = dmlparse(scanner);

    if (fStatus == 0)
    {
        char* str;
        valbuf_t valueBuffer = get_valbuffer();

        for (unsigned int i = 0; i < valueBuffer.size(); i++)
        {
            str = valueBuffer[i];

            if (str)
            {
                if (i > 0)
                    fParseTree.fSqlText += " ";

                fParseTree.fSqlText += str;
            }
        }
    }

    free_copybuffer();
    return fStatus;
}

const ParseTree& DMLParser::getParseTree()
{
    if (!good())
    {
        throw logic_error("The ParseTree is invalid");
    }

    return fParseTree;

}

bool DMLParser::good()
{
    return fStatus == 0;
}

void DMLParser::setDefaultSchema(std::string schema)
{
    set_defaultSchema(schema);
}

DMLFileParser::DMLFileParser()
    : DMLParser()
{}

int DMLFileParser::parse(const string& fileName)
{
    fStatus = -1;

    ifstream ifdml;
    ifdml.open(fileName.c_str());

    if (!ifdml.is_open())
    {
        perror(fileName.c_str());
        return fStatus;
    }

    char dmlbuf[1024 * 1024];
    unsigned length;
    ifdml.seekg(0, ios::end);
    length = ifdml.tellg();
    ifdml.seekg(0, ios::beg);

    if (length > sizeof(dmlbuf) - 1)
    {
        throw length_error("DMLFileParser has file size hard limit of 16K.");
    }

    std::streamsize rcount;
    rcount = ifdml.readsome(dmlbuf, sizeof(dmlbuf) - 1);

    if (rcount < 0)
        return fStatus;

    dmlbuf[rcount] = 0;

    // cout << endl << fileName << "(" << rcount << ")" << endl;
    //cout << "-----------------------------" << endl;
    //cout << dmlbuf << endl;

    return DMLParser::parse(dmlbuf);
}

void end_sql(void)
{

}                                             /* end_sql */

}                                                 // dmlpackage
