using System.Diagnostics.CodeAnalysis;

namespace SharpChat {
    public readonly struct Colour {
        public byte Red { get; }
        public byte Green { get; }
        public byte Blue { get; }
        public bool Inherits { get; }

        public static Colour None { get; } = new();

        public Colour() {
            Red = 0;
            Green = 0;
            Blue = 0;
            Inherits = true;
        }

        public Colour(byte red, byte green, byte blue) {
            Red = red;
            Green = green;
            Blue = blue;
            Inherits = false;
        }

        public override bool Equals([NotNullWhen(true)] object? obj) {
            return obj is Colour colour && Equals(colour);
        }
       
        public bool Equals(Colour other) {
            return Red == other.Red
                && Green == other.Green
                && Blue == other.Blue
                && Inherits == other.Inherits;
        }

        public override int GetHashCode() {
            return ToMisuzu();
        }

        public override string ToString() {
            return Inherits
                ? "inherit"
                : string.Format("#{0:x2}{1:x2}{2:x2}", Red, Green, Blue);
        }

        public int ToRawRGB() {
            return (Red << 16) | (Green << 8) | Blue;
        }

        public static Colour FromRawRGB(int rgb) {
            return new(
                (byte)((rgb >> 16) & 0xFF),
                (byte)((rgb >> 8) & 0xFF),
                (byte)(rgb & 0xFF)
            );
        }

        private const int MSZ_INHERIT = 0x40000000;

        public int ToMisuzu() {
            return Inherits ? MSZ_INHERIT : ToRawRGB();
        }

        public static Colour FromMisuzu(int raw) {
            return (raw & MSZ_INHERIT) > 0
                ? None
                : FromRawRGB(raw);
        }

        public static bool operator ==(Colour left, Colour right) {
            return left.Equals(right);
        }

        public static bool operator !=(Colour left, Colour right) {
            return !(left == right);
        }
    }
}