<?php

namespace onespace\tools\widgets\luminance;

use Exception;
use Yii;
use yii\base\Widget;

/**
 * Widget helper for calculating the luminance of a hex RGB colour value.
 * 
 * @author Gareth Palmer <gareth@one-space.co.za>
 */

final class Luminance extends Widget {

    /**
     * REQUIRED. The RGB Hex colour value. Can be parsed with or without a leading #.
     *
     * @var string
     * 
     * @access  public
     */

    public string $hex;

    /**
     * OPTIONAL. The light text colour. Default is WHITE.
     *
     * @var string  Default: `#fff`
     * 
     * @access  public
     */

    public string $lightColour = '#fff';

    /**
     * OPTIONAL. The dark text colour. Default is BLACK.
     *
     * @var string  Default: `#000`
     * 
     * @access  public
     */

    public string $darkColour = '#000';

    /**
     * The luminance float value calculated from the RGB hex.
     *
     * @var float
     * 
     * @access  private
     */

    private float $luminance;


    /**
     * {@inheritdoc}
     *
     * @return void
     * 
     * @access  public
     */

    public function init(): void {
        parent::init();
        if (!isset($this->hex)) {
            throw new Exception("Hex colour not set.");
        }
        if (!$this->validate_hex()) {
            throw new Exception("Not a valid colour hex.");
        }
    }


    /**
     * {@inheritdoc}
     *
     * @return void
     * 
     * @access  public
     */

    public function run(): void {
        parent::run();
        $r = hexdec(substr($this->hex, 1, 2));
        $g = hexdec(substr($this->hex, 3, 2));
        $b = hexdec(substr($this->hex, 5, 2));

        // calculate the relative luminance using the formula from the WCAG 2.0 guidelines
        $this->luminance = (0.2126 * $r + 0.7152 * $g + 0.0722 * $b) / 255;
    }


    /**
     * {@inheritdoc}
     * 
     * Completely overwrites `parent::widget`, so that it returns a new instance of this class for method chaining.
     *
     * @param array $config
     *
     * @return onespace\tools\helpers\Luminance
     * 
     * @access  public
     */

    public static function widget($config = []): Luminance {
        try {
            /* @var $widget Widget */
            $config['class'] = get_called_class();
            $widget = Yii::createObject($config);
            $out = '';
            if ($widget->beforeRun()) {
                $result = $widget->run();
                $out = $widget->afterRun($result);
            }
        } catch (\Exception $e) {
            // close the output buffer opened above if it has not been closed already
            if (ob_get_level() > 0) {
                ob_end_clean();
            }
            throw $e;
        } catch (\Throwable $e) {
            // close the output buffer opened above if it has not been closed already
            if (ob_get_level() > 0) {
                ob_end_clean();
            }
            throw $e;
        }
        return $widget;
    }


    /**
     * Whether the luminance of the parsed hex is light.
     *
     * @return boolean
     * 
     * @access  public
     */

    public function isLight(): bool {
        return $this->luminance > 0.5;
    }


    /**
     * Whether the luminance of the parsed hex is dark.
     *
     * @return boolean
     * 
     * @access  public
     */

    public function isDark(): bool {
        return $this->luminance <= 0.5;
    }


    /**
     * Added method for returning the appropriate text colour based on the luminance of the parsed RGB hex.
     * 
     * @return string
     * 
     * @access  public
     */

    public function textColour(): string {
        if ($this->isLight()) {
            return $this->darkColour;
        }
        return $this->lightColour;
    }

    /**
     * Perform a validation and cleanup of the hex RGB value.
     *
     * @return boolean
     * 
     * @access  private
     */

    private function validate_hex(): bool {
        $colour = ltrim($this->hex, "# \t\n\r\0\x0B");
        $this->hex = '#' . $colour;
        return preg_match('/^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/', $colour);
    }
}
