### MIT License

### Copyright (c) 2024 Kevin J. Walters

### Permission is hereby granted, free of charge, to any person obtaining a copy
### of this software nd associated documentation files (the "Software"), to deal
### in the Software without restriction, including without limitation the rights
### to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
### copies of the Software, and to permit persons to whom the Software is
### furnished to do so, subject to the following conditions:

### The above copyright notice and this permission notice shall be included in all
### copies or substantial portions of the Software.

### THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
### IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
### FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
### AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
### LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
### OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
### SOFTWARE.


import array
import math

import bitmaptools


### This is some basic arc drawing code for single pixel width curves
### drawn with some straight line segments
### There are going to be more efficient ways to draw arcs ...

### Yet More Graphics Primitives
class YMGP:

    ###
    ### Angle is from anti-clockwise from east, For angles 0 is right, pi/2 is up

    @classmethod
    def draw_arc_cr_rad(cls,
                        bitmap,
                        cx,
                        cy,
                        radius,
                        start_angle,
                        angle,
                        pal_idx,
                        *,
                        segments=None):
        """ ."""
        ### pylint: disable=too-many-locals

        l_segments = 2 + round(angle * radius / 10.0) if segments is None else segments

        num_points = l_segments + 1
        x_points = array.array("h", [0] * num_points)
        y_points = array.array("h", [0] * num_points)
        p_idx = 0
        for i in range(num_points):
            alpha = i * angle / l_segments + start_angle
            x0 = radius * math.cos(alpha)
            y0 = radius * math.sin(alpha)
            x_points[p_idx] = round(cx + x0)
            y_points[p_idx] = round(cy - y0)  ### TODO does this need to be negative
            p_idx = p_idx + 1

        bitmaptools.draw_polygon(bitmap,
                                 x_points,
                                 y_points,
                                 pal_idx,
                                 close=False)


    @classmethod
    def draw_arc_points(cls,
                        bitmap,
                        x1,
                        y1,
                        x2,
                        y2,
                        radius,
                        pal_idx,
                        *,
                        segments=None):
        """Draw an arc from x1,y1 to x2,y2 with radius using segments number of lines."""
        ### pylint: disable=too-many-locals

        ### Calculate vector components for the line
        ldx = x2 - x1
        ldy = y2 - y1
        line_len = math.sqrt(ldx * ldx + ldy * ldy)
        ### Angle is from anti-clockwise from east
        line_angle = 0.0 - math.atan2(ldy, ldx)

        line_over_diameter = line_len / (2 * radius)
        if line_over_diameter > 1.0:
            line_over_diameter = 1.0
            ##raise ValueError("Radius is not large enough")

        half_angle = math.asin(line_over_diameter)
        height = radius * math.cos(half_angle)

        cx = x1 + ldx / 2 + height * (ldy / line_len)
        cy = y1 + ldy / 2 - height * (ldx / line_len)

        cls.draw_arc_cr_rad(bitmap,
                            cx,
                            cy,
                            radius,
                            line_angle - half_angle - math.pi / 2,
                            2 * half_angle,
                            pal_idx,
                            segments=segments)