#!/usr/pkg/bin/ruby34

require 'term/ansicolor'
include Term::ANSIColor
require 'tins/xt'
include Tins::GO
require "complex"

$width, $height = Tins::Terminal.cols, Tins::Terminal.lines
$height *= 2

def color_random
  (1..3).map { rand(255) }
end

def draw_set(rx, ry)
  sx = (rx.end - rx.begin).abs / $width
  sy = (ry.end - ry.begin).abs / $height

  steps = 16
  color = (5.times.map { color_random } + [ 0, 0, 0 ]).map { Attribute[_1] }
  color = color[1..-1].inject(color[0,1]) { |c, x|
    c + c.last.gradient_to(x, steps:)
  }
  iters = color.size - 2

  data = [ [] ]
  for j in 0...$height
    for i in 0...$width
      n, z_n = 0, Complex(0, 0)
      c = Complex(sx * i + rx.begin, sy * j + ry.begin)
      while n <= iters
        break if z_n.abs > 2
        z_n = z_n ** 2 + c
        n += 1
      end
      data.last << n
    end
    data << []
  end
  screen = ''
  (0...$height).step(2) do |j|
    (0...$width).each do |i|
      screen << color(color[data[j][i]]) <<
        on_color(color[data[j + 1][i]]) << ?▀
    end
  end
  print move_home, screen, reset
end

opts = go 'x:y'

Term::ANSIColor.true_coloring = ENV['COLORTERM'] =~ /\A(truecolor|24bit)\z/

rx = opts[?x].full? { |r| Range.new(*(r.split('..', 2).map(&:to_f))) } || (-2.0..1.0)
ry = opts[?y].full? { |r| Range.new(*(r.split('..', 2).map(&:to_f))) } || (-1.0..1.0)

draw_set rx, ry
