/*
 * Copyright (c) 2025 focus-timer contributors
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * Authors: Kamil Prusko <kamilprusko@gmail.com>
 */

namespace Ft
{
    public class ChartGrid : Gtk.Widget
    {
        public Ft.ChartAxis x_axis {
            get {
                return this._x_axis;
            }
        }

        public Ft.ChartAxis y_axis {
            get {
                return this._y_axis;
            }
        }

        public int x_origin {
            get {
                return this._x_origin;
            }
            set {
                this._x_origin = value;
            }
        }

        public int y_origin {
            get {
                return this._y_origin;
            }
            set {
                this._y_origin = value;
            }
        }

        public float line_width {
            get {
                return this._line_width;
            }
            set {
                this._line_width = value;

                this.queue_draw ();
            }
        }

        public bool horizontal {
            get {
                return this._horizontal;
            }
            set {
                this._horizontal = value;

                this.queue_draw ();
            }
        }

        public bool vertical {
            get {
                return this._vertical;
            }
            set {
                this._vertical = value;

                this.queue_draw ();
            }
        }

        private unowned Ft.ChartAxis?   _x_axis = null;
        private unowned Ft.ChartAxis?   _y_axis = null;
        private int                     _x_origin = 0;
        private int                     _y_origin = 0;
        private float                   _line_width = 1.0f;
        private bool                    _horizontal = true;
        private bool                    _vertical = true;

        static construct
        {
            set_css_name ("chartgrid");
        }

        public ChartGrid (Ft.ChartAxis? x_axis,
                          Ft.ChartAxis? y_axis)
        {
            this._x_axis = x_axis;
            this._y_axis = y_axis;

            if (this._x_axis != null) {
                this._x_axis.configured.connect (() => this.queue_draw ());
            }

            if (this._y_axis != null) {
                this._y_axis.configured.connect (() => this.queue_draw ());
            }
        }

        public override void snapshot (Gtk.Snapshot snapshot)
        {
            var width        = (float) this.get_width ();
            var height       = (float) this.get_height ();
            var stroke       = new Gsk.Stroke (this._line_width);
            var path_builder = new Gsk.PathBuilder ();

            // round line positions to full pixels
            var line_offset = ((this._line_width - 1.0f) % 2.0f - 1.0f).abs () * 0.5f;

            var color = this.get_color ();
            color.alpha *= 0.5f;

            if (this.horizontal && this._y_axis != null)
            {
                var y_scale = -this._y_axis.scale;

                foreach (var tick_value in this._y_axis.get_ticks ())
                {
                    var line_y = Math.roundf (tick_value * y_scale + (float) this._y_origin) +
                                 line_offset;

                    path_builder.move_to (0.0f, line_y);
                    path_builder.line_to (width, line_y);
                }
            }

            if (this.vertical && this._x_axis != null)
            {
                var x_scale = this._x_axis.scale;

                foreach (var tick_value in this._x_axis.get_ticks ())
                {
                    var line_x = Math.roundf (tick_value * x_scale + (float) this._x_origin) +
                                 line_offset;

                    path_builder.move_to (line_x, 0.0f);
                    path_builder.line_to (line_x, height);
                }
            }

            snapshot.append_stroke (path_builder.to_path (), stroke, color);
        }

        public override void dispose ()
        {
            this._x_axis = null;
            this._y_axis = null;

            base.dispose ();
        }
    }
}
