/*
    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 flowstyle.cpp Flow specific style and context definitions 
* @ingroup libflow_files */


#include <cstring>
#include "flowstyle.h"
#include "flowchart.h"

using namespace flow;

///Control which components are used
FlowStyle::FlowStyle(EStyleType tt, EColorMeaning cm, EArcArrowType a,
                   bool t, bool l, bool f, bool s, bool nu, bool shp, bool x):
    SimpleStyleWithArrow<TwoArrowHeads>(tt,cm, a, t, l, f, s, nu, shp),
    f_flow(x)
{
    //Add code that marks which of your attributes can be assigned
    //empty the style.
}

//Has all the components, but is empty
FlowStyle::FlowStyle(EStyleType tt, EColorMeaning cm) :
    SimpleStyleWithArrow<TwoArrowHeads>(tt, cm),
    f_flow(true)
{
    //Add all your components
    //EMpty the style
}

void FlowStyle::Empty()
{
    //clear all your attributes
    SimpleStyleWithArrow<TwoArrowHeads>::Empty();
}

void FlowStyle::MakeCompleteButText()
{
    //set default value to all your attributes, except text
    //(so that global text options can be added)
    SimpleStyleWithArrow<TwoArrowHeads>::MakeCompleteButText();
}



Style &FlowStyle::operator += (const Style &toadd)
{
    SimpleStyleWithArrow<TwoArrowHeads>::operator+=(toadd);
    const FlowStyle* p = dynamic_cast<const FlowStyle *>(&toadd);
    if (p) {
        //Write your own code adding an FlowStyle to another
    }
    return *this;
}


/** Add an atribute to a style. Provide errors if needed and return true
 * if the attrbute name was recognized as one that applies to us.*/
bool FlowStyle::AddAttribute(const Attribute & a, Chart *chart)
{
    if (f_flow && a.Is("flow")) {
        //Write your own code adding the attribute
        return true;
    }
    if (f_flow && a.EndsWith("flow")) {
        //Write your own code adding the attribute
        return true;
    }
    return SimpleStyleWithArrow<TwoArrowHeads>::AddAttribute(a, chart);
}

void FlowStyle::AttributeNames(Csh &csh) const
{
    //Add your own attributes
    if (f_flow)
        csh.AddToHints(CshHint(csh.HintPrefix(COLOR_ATTRNAME)+"flow",
            "Explanation for attribute flow",
            EHintType::ATTR_NAME));
    SimpleStyleWithArrow<TwoArrowHeads>::AttributeNames(csh);
}

bool FlowStyle::AttributeValues(std::string_view attr, Csh &csh) const
{
    //test for your own attributes and add their potential values
    if (CaseInsensitiveEqual(attr, "flow") && f_flow) {
        csh.AddToHints(CshHint(csh.HintPrefixNonSelectable() + "<number: \b0.0..1.0\b>",
            "Explain this attribute value",
            EHintType::ATTR_VALUE, false));
        csh.AddToHints(CshHint(csh.HintPrefixNonSelectable() + "auto",
            "Explain this attibute value.",
            EHintType::ATTR_VALUE, false));
        return true;
    }
    return SimpleStyleWithArrow<TwoArrowHeads>::AttributeValues(attr, csh);
}

void FlowContext::ApplyContextContent(const FlowContext &o)
{
    ContextBase::ApplyContextContent(o);
    if (o.IsFull()) {
        //copy assign all the context members you have added                  
    } else {
        //merge all the context members you have added                  
    }
}

void FlowContext::ApplyContextContent(FlowContext &&o)
{
    if (o.IsFull()) {
        //move assign all the context members you have added                  
    } else {
        //move merge all the context members you have added                  
    }
    ContextBase::ApplyContextContent(std::move(o));
}





void FlowContext::Empty()
{
    ContextBase<FlowStyle>::Empty();
    styles["step"] = FlowStyle(EStyleType::DEFAULT, EColorMeaning::LINE_ARROW_TEXT,
        EArcArrowType::NONE, true, true, true, true, true, false, false);
    //line, fill, text, shadow, numbering
    styles["if"] = styles["start"] = styles["stop"] = styles["step"];

    styles["arrow"] = FlowStyle(EStyleType::DEFAULT, EColorMeaning::LINE_ARROW_TEXT,
        EArcArrowType::ARROW, true, true, false, false, false, false, false);
    //arrow, line, text
}

void FlowContext::Plain()
{
    Empty();
    ContextBase<FlowStyle>::Plain();
    styles["step"].write().MakeCompleteButText();
    styles["if"] = styles["step"];
    styles["start"].write().MakeCompleteButText();
    styles["start"].write().line.type = ELineType::DOUBLE;
    styles["start"].write().line.corner = ECornerType::ROUND;
    styles["start"].write().line.radius = 15;
    styles["stop"] = styles["start"];
    styles["arrow"].write().MakeCompleteButText();
    styles["arrow"].write().arrow.write().SetType(EArrowEnd::END, EArrowType::EMPTY);
}


