/*
    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 contour_debug.cpp Defines contour debug facilities.
 * @ingroup contour_files
 */

#include <atomic>
#include "canvas.h"
#include "contour_debug.h"
#include "cgen_shapes.h"


namespace contour {
namespace debug {

} //namespace debug
} //namespace contour

using namespace contour::debug;

DebugCanvas::DebugCanvas(std::string_view fn, const Block &place, const char* text)
{
    sf.Default();
    sf.Apply("\\mn(2)\\ms(1)");
    canvas = std::make_unique<Canvas>(Canvas::PDF, place.CreateExpand(10), 0, fn, XY(10,10));
    if (text && canvas && !canvas->cannot_draw()) {
        cairo_set_source_rgb(canvas->GetContext(), 0, 0, 0);
        cairo_move_to(canvas->GetContext(), 0, 0);
        thread_safe_cairo_show_text(canvas->GetContext(), text);
    }
}

void contour::debug::DebugCanvas::DrawX(const XY &xy)
{
    if (marker_size==0) return;
    XY wh(marker_size/2, marker_size/2);
    canvas->Line(xy-wh, xy+wh, line);
    wh.x *= -1;
    canvas->Line(xy-wh, xy+wh, line);
}

void contour::debug::DebugCanvas::DrawLabel(std::string s, const XY &xy, unsigned n)
{
    static ShapeCollection shapes;
    size_t f = s.find("%x");
    if (f != std::string::npos)
        s.replace(f, 2, to_string(xy.x, 1));
    f = s.find("%y");
    if (f != std::string::npos)
        s.replace(f, 2, to_string(xy.y, 1));
    f = s.find("%n");
    if (f != std::string::npos)
        s.replace(f, 2, std::to_string(n));
    Label l(s, *canvas, shapes, sf);
    l.Draw(*canvas, shapes, xy.x, xy.x, xy.y);
}

void contour::debug::DebugCanvas::Draw(const Edge & e, bool, bool cont2, std::string s, std::string en, unsigned n)
{
    canvas->Line(e, line);
    DrawX(e.GetStart());
    if (!cont2) DrawX(e.GetEnd());
    DrawLabel(s, e.GetStart(), n);
    if (!cont2)
        DrawLabel(en, e.GetEnd(), n);
}

void contour::debug::DebugCanvas::Draw(const SimpleContour::ExpandMetaData & e, bool cont1, bool cont2, std::string s, std::string en, unsigned n)
{
    std::string cp_type;
    switch (e.cross_type) {
    default:
        break;
    case Edge::CP_DEGENERATE: cp_type = "deg"; break;
    case Edge::CP_EXTENDED: cp_type = "ext"; break;
    case Edge::CP_INVERSE: cp_type = "inv"; break;
    case Edge::CP_REAL: cp_type = "real"; break;
    case Edge::CP_TRIVIAL: cp_type = "triv"; break;
    case Edge::NO_CP_PARALLEL: cp_type = "parallel"; break;
    }
    size_t f = s.find("%t");
    if (f != std::string::npos)
        s.replace(f, 2, cp_type);
    Draw(static_cast<const Edge&>(e), cont1, cont2, s, en, n);
}

std::atomic_uint32_t canvas_seq = 1;
unsigned contour::debug::get_canvas_seq() noexcept {
    return canvas_seq.fetch_add(1);
}

