#!/usr/bin/env python3
"""
Random MOTD: shows a quote (with author if available) in a
cowsay-style bubble, colorized with a lolcat-style rainbow gradient.
Only depends on the stdlib -> no need to install cowsay/lolcat.

Expected format in quotes.txt: one quote per line, "title|author" or
just "title" if the author is unknown.

Typical setup
mkdir -p /opt/motd
copy motd.py znd quotes.txt to /opt/motd
vi /etc/profile.d/quote-motd.sh
-- content
#!/bin/sh
# only for interactive shells
case "$-" in
    *i*) python3 /opt/motd/motd.py ;;
esac
-- end content
chmod +x /etc/profile.d/quote-motd.sh

Usage:
   python3 motd.py [path/to/quotes.txt]
"""
import math
import os
import random
import sys
import textwrap

QUOTES_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "quotes.txt")
BUBBLE_WIDTH = 40

COW = r"""
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
"""


def pick_quote(path):
   with open(path, encoding="utf-8") as f:
      raw_lines = [l.strip() for l in f if l.strip()]
   if not raw_lines:
      return "...", None

   line = random.choice(raw_lines)
   if "|" in line:
      quote, author = line.split("|", 1)
      return quote.strip(), author.strip()
   return line, None


def build_bubble(quote, author, width=BUBBLE_WIDTH):
   lines = textwrap.wrap(f'"{quote}"', width=width) or ['""']
   if author:
      lines.append("")
      lines.append(f"-{author}")

   inner = max(len(l) for l in lines)

   padded = [l.ljust(inner) for l in lines]
   if author:
      padded[-1] = lines[-1].rjust(inner)  # right-align the author line

   top = " " + "_" * (inner + 2)
   bottom = " " + "-" * (inner + 2)

   body = []
   if len(padded) == 1:
      body.append(f"< {padded[0]} >")
   else:
      body.append(f"/ {padded[0]} \\")
      for l in padded[1:-1]:
         body.append(f"| {l} |")
      body.append(f"\\ {padded[-1]} /")

   return "\n".join([top] + body + [bottom]) + COW


def rainbow(i):
   r = int(math.sin(i) * 127 + 128)
   g = int(math.sin(i + 2 * math.pi / 3) * 127 + 128)
   b = int(math.sin(i + 4 * math.pi / 3) * 127 + 128)
   return r, g, b


def lolcat(text, freq=0.25, spread=6.0):
   seed = random.uniform(0, 2 * math.pi)
   out_lines = []
   for y, line in enumerate(text.split("\n")):
      chars = []
      for x, ch in enumerate(line):
         if ch.isspace():
            chars.append(ch)
            continue
         i = seed + x / spread + y * freq
         r, g, b = rainbow(i)
         chars.append(f"\x1b[38;2;{r};{g};{b}m{ch}")
      chars.append("\x1b[0m")
      out_lines.append("".join(chars))
   return "\n".join(out_lines)


def main():
   path = sys.argv[1] if len(sys.argv) > 1 else QUOTES_FILE
   quote, author = pick_quote(path)
   bubble = build_bubble(quote, author)
   print(lolcat(bubble))


if __name__ == "__main__":
   main()

