/*
    This file is part of Msc-generator.
	Copyright (C) 2008-2024 Zoltan Turanyi
	Distributed under GNU Affero General Public License.

    Msc-generator is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Msc-generator 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Msc-generator.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file xxxchart.cpp The definition for the XxxChart class and all of the "xxx" language.
* @ingroup libxxx_files */

/** @defgroup libxxx The engine of the xxx library
@ingroup libs

 More documentation is coming.

*/

/** @defgroup libxxx_files Files for the xxx library.
* @ingroup libxxx*/


#include "canvas.h"
#include "xxxchart.h"
#include "xxxcsh.h"
#include "xxx_parser_compile.h"

using namespace xxx;

XxxInstruction::XxxInstruction(XxxChart&) {
}

std::unique_ptr<Csh> XxxChart::CshFactory(Csh::FileListProc proc, const LanguageCollection* languages) const
{
    return std::make_unique<XxxCsh>(proc, languages);
}

std::map<std::string, std::string> XxxChart::RegisterLibraries() const
{
    //Add any libraries you use here (no need to add cairo),
    //like "mylib v5.0.0" in UTF-8
    return {};
}



XxxChart::XxxChart(FileReadProcedure *p, void *param, const LanguageCollection* languages) : ChartBase(p, param, languages)
{
    Contexts.emplace_back(true, EContextParse::NORMAL, EContextCreate::PLAIN, FileLineCol());  //creates new, plain context
    Designs.emplace("plain", Contexts.back());
}

XxxChart::~XxxChart()
{
    //Your own destructor
}


XxxInstrList XxxChart::PopContext()
{
    Contexts.pop_back();
    //you may return an instruction if needed. It will be the last instruction
    //in the list of instructions for this scope
    return {};
}


bool XxxChart::AddCommandLineArg(const std::string & /*arg*/)
{
    return false;
}

void XxxChart::AddCommandLineOption(const Attribute & /*a*/)
{
}

std::unique_ptr<XxxInstruction> XxxChart::AddAttribute(const Attribute &a)
{
    if (AddDesignAttribute(a)) return {};
    //TODO: Apply chart options here that do not apply to designs
    return {}; //you may return an instruction if the option results in one
}

bool XxxChart::AddDesignAttribute(const Attribute&)
{
    //TODO: Apply chart options here that also apply to designs
    return false; //return true if you have recognized & handled the chart option
}



bool XxxChart::DeserializeGUIState(std::string_view)
{
    return true;
}

std::string XxxChart::SerializeGUIState() const
{
    return std::string();
}

bool XxxChart::ControlClicked(Element*, EGUIControlType)
{
    return false;
}

bool XxxChart::ApplyForcedDesign(const string & name)
{
    //this is called before parsing
    auto i = Designs.find(name);
    if (i==Designs.end())
        return false;
    ignore_designs = true;
    Contexts.back().ApplyContextContent(i->second);
    return Chart::ApplyForcedDesign(name);
}

/** Adds a chart option. Currently this is only 'pedantic'.
 * If not a chart option, try adding it to the graph/subgraph we are in. */
 bool XxxChart::AddChartOption(const Attribute &a)
{
    if (a.Is("xxx")) {
        //add your chart option to MyCurrentContext()
        return true;
    }
    //Error if not recognized
    Error.Error(a, false, "Unrecognized chart option. Ignoring it.");
    return false;
}

void XxxChart::ParseText(std::string_view input, const FileLineCol& first_char)
{
    //if you support progress::
    //Progress.RegisterParse(len);
    sv_reader<false> reader(input, first_char);
    procedure_parse_helper proc_helper;
    xxx_compile_parse(*this, proc_helper, reader); //return value ignored
}

void XxxChart::CompleteParse(bool, bool, XY, bool, bool)
{
    Canvas canvas(Canvas::Empty::Query);
    pageBreakData.clear();
    //Consider the copyright text
    StringFormat sf;
    sf.Default();
    XY crTexSize = Label(copyrightText, canvas, Shapes, sf).getTextWidthHeight().RoundUp();
    copyrightTextHeight = crTexSize.y;

    //Do the layout of your chart here

    total += Block(0, 1, 0, 1); //have at least this size
    if (total.x.till < crTexSize.x) total.x.till = crTexSize.x;
    if (pageBreakData.size()==0)
        pageBreakData.emplace_back(XY(0, 0), XY(0, 0)); //we *must* have one page
    //We keep graphs in the force_collapse list even if they do not really exist.

    Error.Sort();
}


void XxxChart::CollectIsMapElements(Canvas & /*canvas*/)
{
}

void XxxChart::RegisterAllLabels()
{
}

void XxxChart::Draw(Canvas & c, bool pageBreaks, unsigned page)
{
    if (page) {
        //draw page X
    } else {
        //draw background

        if (pageBreaks)
            DrawPageBreaks(c);

        //draw all pages
    }
    //TODO: make sure you fill bkFill to help determining bkground for headers and footers.
}


void XxxChart::SetToEmpty()
{
    //Your own code to clear all internal data and create a chart that shows an empty page
    //(same as if you had parsed the empty file)
}