#include "pch.h"
#include "legacy_ui_node_attributes.h"

#include "log.h"
#include "node.h"

namespace pp::panopainter {

void parse_legacy_ui_node_attribute(Node& node, kAttribute ka, const tinyxml2::XMLAttribute* attr)
{
    switch (ka)
    {
    case kAttribute::id:
        node.m_nodeID_s = attr->Value();
        node.m_nodeID = const_hash(attr->Value());
        break;
    case kAttribute::Width:
        if (strcmp(attr->Value(), "auto") == 0)
        {
            YGNodeStyleSetWidth(node.y_node, YGUndefined);
            YGNodeStyleSetWidthPercent(node.y_node, YGUndefined);
            node.auto_width = true;
        }
        else
        {
            if (strchr(attr->Value(), '%'))
                YGNodeStyleSetWidthPercent(node.y_node, attr->FloatValue());
            else
                YGNodeStyleSetWidth(node.y_node, attr->FloatValue());
            node.auto_width = false;
        }
        break;
    case kAttribute::MinWidth:
        YGNodeStyleSetMinWidth(node.y_node, attr->FloatValue());
        break;
    case kAttribute::MaxWidth:
        YGNodeStyleSetMaxWidth(node.y_node, attr->FloatValue());
        break;
    case kAttribute::Height:
        if (strcmp(attr->Value(), "auto") == 0)
        {
            YGNodeStyleSetHeight(node.y_node, YGUndefined);
            YGNodeStyleSetHeightPercent(node.y_node, YGUndefined);
            node.auto_height = true;
        }
        else
        {
            if (strchr(attr->Value(), '%'))
                YGNodeStyleSetHeightPercent(node.y_node, attr->FloatValue());
            else
                YGNodeStyleSetHeight(node.y_node, attr->FloatValue());
            node.auto_height = false;
        }
        break;
    case kAttribute::MinHeight:
        YGNodeStyleSetMinHeight(node.y_node, attr->FloatValue());
        break;
    case kAttribute::MaxHeight:
        YGNodeStyleSetMaxHeight(node.y_node, attr->FloatValue());
        break;
    case kAttribute::Grow:
        YGNodeStyleSetFlexGrow(node.y_node, attr->FloatValue());
        break;
    case kAttribute::Shrink:
        YGNodeStyleSetFlexShrink(node.y_node, attr->FloatValue());
        break;
    case kAttribute::FlexDir:
    {
        YGFlexDirection dir = YGFlexDirectionRow;
        if (strcmp("col", attr->Value()) == 0)
            dir = YGFlexDirectionColumn;
        else if (strcmp("col-reverse", attr->Value()) == 0)
            dir = YGFlexDirectionColumnReverse;
        else if (strcmp("row", attr->Value()) == 0)
            dir = YGFlexDirectionRow;
        else if (strcmp("row-reverse", attr->Value()) == 0)
            dir = YGFlexDirectionRowReverse;
        YGNodeStyleSetFlexDirection(node.y_node, dir);
        break;
    }
    case kAttribute::FlexWrap:
        YGNodeStyleSetFlexWrap(node.y_node, attr->IntValue() ? YGWrapWrap : YGWrapNoWrap);
        break;
    case kAttribute::Justify:
    {
        YGJustify v = YGJustifyFlexStart;
        if (strcmp("center", attr->Value()) == 0)
            v = YGJustifyCenter;
        else if (strcmp("flex-start", attr->Value()) == 0)
            v = YGJustifyFlexStart;
        else if (strcmp("flex-end", attr->Value()) == 0)
            v = YGJustifyFlexEnd;
        else if (strcmp("space-around", attr->Value()) == 0)
            v = YGJustifySpaceAround;
        else if (strcmp("space-between", attr->Value()) == 0)
            v = YGJustifySpaceBetween;
        YGNodeStyleSetJustifyContent(node.y_node, v);
        break;
    }
    case kAttribute::Align:
    {
        YGAlign v = YGAlignStretch;
        if (strcmp("stretch", attr->Value()) == 0)
            v = YGAlignStretch;
        else if (strcmp("flex-start", attr->Value()) == 0)
            v = YGAlignFlexStart;
        else if (strcmp("flex-end", attr->Value()) == 0)
            v = YGAlignFlexEnd;
        else if (strcmp("center", attr->Value()) == 0)
            v = YGAlignCenter;
        YGNodeStyleSetAlignItems(node.y_node, v);
        break;
    }
    case kAttribute::Positioning:
    {
        YGPositionType v = YGPositionTypeRelative;
        if (strcmp("relative", attr->Value()) == 0)
            v = YGPositionTypeRelative;
        else if (strcmp("absolute", attr->Value()) == 0)
            v = YGPositionTypeAbsolute;
        YGNodeStyleSetPositionType(node.y_node, v);
        break;
    }
    case kAttribute::Position:
    {
        glm::vec4 v;
        int n = sscanf(attr->Value(), "%f %f %f %f", &v.x, &v.y, &v.z, &v.w);
        if (n == 2)
        {
            YGNodeStyleSetPosition(node.y_node, YGEdgeLeft, v.x);
            YGNodeStyleSetPosition(node.y_node, YGEdgeTop, v.y);
        }
        else
        {
            YGNodeStyleSetPadding(node.y_node, YGEdgeLeft, v.x);
            YGNodeStyleSetPadding(node.y_node, YGEdgeTop, v.y);
            YGNodeStyleSetPadding(node.y_node, YGEdgeRight, v.z);
            YGNodeStyleSetPadding(node.y_node, YGEdgeBottom, v.w);
        }
        break;
    }
    case kAttribute::Padding:
    {
        glm::vec4 pad;
        int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w);
        if (n == 1)
        {
            YGNodeStyleSetPadding(node.y_node, YGEdgeTop, pad.x);
            YGNodeStyleSetPadding(node.y_node, YGEdgeRight, pad.x);
            YGNodeStyleSetPadding(node.y_node, YGEdgeBottom, pad.x);
            YGNodeStyleSetPadding(node.y_node, YGEdgeLeft, pad.x);
        }
        else
        {
            YGNodeStyleSetPadding(node.y_node, YGEdgeTop, pad.x);
            YGNodeStyleSetPadding(node.y_node, YGEdgeRight, pad.y);
            YGNodeStyleSetPadding(node.y_node, YGEdgeBottom, pad.z);
            YGNodeStyleSetPadding(node.y_node, YGEdgeLeft, pad.w);
        }
        break;
    }
    case kAttribute::Margin:
    {
        glm::vec4 pad;
        int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w);
        if (n == 1)
        {
            YGNodeStyleSetMargin(node.y_node, YGEdgeTop, pad.x);
            YGNodeStyleSetMargin(node.y_node, YGEdgeRight, pad.x);
            YGNodeStyleSetMargin(node.y_node, YGEdgeBottom, pad.x);
            YGNodeStyleSetMargin(node.y_node, YGEdgeLeft, pad.x);
        }
        else
        {
            YGNodeStyleSetMargin(node.y_node, YGEdgeTop, pad.x);
            YGNodeStyleSetMargin(node.y_node, YGEdgeRight, pad.y);
            YGNodeStyleSetMargin(node.y_node, YGEdgeBottom, pad.z);
            YGNodeStyleSetMargin(node.y_node, YGEdgeLeft, pad.w);
        }
        break;
    }
    case kAttribute::FloodEvents:
        node.m_flood_events = attr->BoolValue();
        break;
    case kAttribute::MouseCapture:
        node.m_force_mouse_capture = attr->BoolValue();
        break;
    case kAttribute::AspectRatio:
        YGNodeStyleSetAspectRatio(node.y_node, attr->FloatValue());
        break;
    case kAttribute::RTL:
        if (strcmp("rtl", attr->Value()) == 0)
            node.SetRTL(YGDirectionRTL);
        else if (strcmp("ltr", attr->Value()) == 0)
            node.SetRTL(YGDirectionLTR);
        else if (strcmp("inherit", attr->Value()) == 0)
            node.SetRTL(YGDirectionInherit);
        else
        {
            LOG("Attribute %s for RTL unrecognized", attr->Value());
        }
    default:
        break;
    }
}

} // namespace pp::panopainter
