#!/usr/bin/python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk

def rgb_to_hsv(r, g, b):
    M, m = max(r,g,b), min(r,g,b)
    d = M - m
    v = M
    s = d/M if M else 0
    if d == 0: h = 0
    elif M == r: h = (g-b)/d % 6
    elif M == g: h = (b-r)/d + 2
    else: h = (r-g)/d + 4
    return round(h*60,1), round(s*100,1), round(v*100,1)

class App(Gtk.Window):
    def __init__(self):
        super().__init__(title='Color Palette')
        self.set_default_size(500, 540)
        self.history = []
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)
        vbox.set_margin_top(8); vbox.set_margin_bottom(8)
        vbox.set_margin_start(8); vbox.set_margin_end(8)
        self.add(vbox)
        self.chooser = Gtk.ColorChooserWidget()
        self.chooser.connect('notify::rgba', self.color_changed)
        vbox.pack_start(self.chooser, True, True, 0)
        # values display
        grid = Gtk.Grid(column_spacing=8, row_spacing=4)
        grid.set_margin_top(4)
        self.val_labels = {}
        self.copy_btns = {}
        for i, fmt in enumerate(['HEX','RGB','HSV']):
            lbl = Gtk.Label(label=f'{fmt}:', xalign=0)
            grid.attach(lbl, 0, i, 1, 1)
            val = Gtk.Entry(); val.set_editable(False); val.set_width_chars(26)
            grid.attach(val, 1, i, 1, 1)
            self.val_labels[fmt] = val
            btn = Gtk.Button(label='Copy')
            btn.connect('clicked', self.copy_value, fmt)
            grid.attach(btn, 2, i, 1, 1)
        vbox.pack_start(grid, False, False, 0)
        # history
        vbox.add(Gtk.Label(label='Recent colors:', xalign=0))
        self.hist_box = Gtk.Box(spacing=4)
        vbox.pack_start(self.hist_box, False, False, 0)
        self.color_changed()
    def color_changed(self, *_):
        rgba = self.chooser.get_rgba()
        r,g,b = rgba.red, rgba.green, rgba.blue
        ri,gi,bi = int(r*255), int(g*255), int(b*255)
        h,s,v = rgb_to_hsv(r,g,b)
        self.val_labels['HEX'].set_text(f'#{ri:02X}{gi:02X}{bi:02X}')
        self.val_labels['RGB'].set_text(f'rgb({ri}, {gi}, {bi})')
        self.val_labels['HSV'].set_text(f'hsv({h}°, {s}%, {v}%)')
    def copy_value(self, _, fmt):
        text = self.val_labels[fmt].get_text()
        clipboard = self.get_clipboard(Gdk.SELECTION_CLIPBOARD)
        clipboard.set_text(text, -1)
        # add to history
        rgba = self.chooser.get_rgba()
        r,g,b = int(rgba.red*255), int(rgba.green*255), int(rgba.blue*255)
        hex_col = f'#{r:02X}{g:02X}{b:02X}'
        if hex_col not in self.history:
            self.history.insert(0, (hex_col, rgba.red, rgba.green, rgba.blue))
            if len(self.history) > 10: self.history.pop()
            self.rebuild_history()
    def rebuild_history(self):
        for ch in self.hist_box.get_children(): self.hist_box.remove(ch)
        for hex_col, r, g, b in self.history:
            btn = Gtk.Button()
            btn.set_size_request(28, 28)
            btn.set_tooltip_text(hex_col)
            btn._color = (r,g,b)
            btn.connect('clicked', self.pick_history)
            css = f'button {{ background: {hex_col}; min-width:28px; min-height:28px; }}'
            provider = Gtk.CssProvider()
            provider.load_from_data(css.encode())
            btn.get_style_context().add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
            self.hist_box.pack_start(btn, False, False, 0)
        self.hist_box.show_all()
    def pick_history(self, btn):
        r,g,b = btn._color
        rgba = Gdk.RGBA(r,g,b,1)
        self.chooser.set_rgba(rgba)

win = App()
win.connect('destroy', Gtk.main_quit)
win.show_all()
Gtk.main()
