#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ASCII animations playground
Usage: python ascii_anim.py
Press Ctrl+C to quit an animation.
"""

import os
import sys
import time
import shutil
import math

def clear():
    # Clear terminal in a cross-platform way
    os.system('cls' if os.name == 'nt' else 'clear')

def spinner(text="Chargement", delay=0.08, rounds=80):
    frames = ['|', '/', '-', '\\']
    for i in range(rounds):
        sys.stdout.write(f"\r{frames[i % len(frames)]} {text} ")
        sys.stdout.flush()
        time.sleep(delay)
    print()

def marquee(text="Hello ASCII!", speed=0.05, loops=3):
    cols = shutil.get_terminal_size((80, 20)).columns
    padding = " " * cols
    s = padding + text + padding
    for _ in range(loops):
        for i in range(len(text) + cols):
            window = s[i:i+cols]
            sys.stdout.write("\r" + window)
            sys.stdout.flush()
            time.sleep(speed)
    print()

def bouncing(text="BOUNCE", speed=0.03, loops=6):
    cols = max(20, shutil.get_terminal_size((80, 20)).columns - len(text))
    pos = 0
    direction = 1
    start = time.time()
    steps = int(loops * (cols * 2))
    for _ in range(steps):
        sys.stdout.write("\r" + " " * pos + text)
        sys.stdout.flush()
        pos += direction
        if pos >= cols or pos <= 0:
            direction *= -1
        time.sleep(speed)
    print()

def wave(text="~wave~", amplitude=3, wavelength=4, speed=0.08, cycles=6):
    cols = shutil.get_terminal_size((80, 20)).columns
    base_x = 0
    for t in range(int(cycles * (wavelength * 4))):
        line = [" "] * cols
        for i, ch in enumerate(text):
            x = (i + base_x) % cols
            y_offset = int(amplitude * math.sin((i + t) / wavelength))
            # create a vertical effect by shifting with newlines — simple 1-line version:
            # we emulate vertical movement by offsetting with spaces (approx)
            pos = x
            line[pos] = ch
        sys.stdout.write("\r" + "".join(line))
        sys.stdout.flush()
        base_x += 1
        time.sleep(speed)
    print()

def typing(text="Ceci est une animation de typing...", speed=0.04):
    for ch in text:
        sys.stdout.write(ch)
        sys.stdout.flush()
        time.sleep(speed)
    print()

def demo_all():
    try:
        clear()
        print("Demo ASCII animations — Ctrl+C pour quitter\n")
        print("1) Spinner")
        spinner("Traitement...", delay=0.06, rounds=60)
        print("\n2) Marquee")
        marquee(">>> Salut ! Ceci est une annonce en défilement <<<", speed=0.03, loops=4)
        print("\n3) Bouncing")
        bouncing(" <3 ", speed=0.01, loops=8)
        print("\n4) Wave (approx.)")
        wave("WAVEEE", amplitude=2, wavelength=3, speed=0.04, cycles=5)
        print("\n5) Typing")
        typing("Voilà — animation typing terminée !", speed=0.03)
    except KeyboardInterrupt:
        print("\nInterrompu. À bientôt!")

if __name__ == "__main__":
    try:
        clear()
        print("Choisis une animation :")
        print("  1) Spinner")
        print("  2) Marquee (défilement)")
        print("  3) Bouncing")
        print("  4) Wave (approx.)")
        print("  5) Typing")
        print("  0) Demo toutes")
        choice = input("Numéro > ").strip()
        clear()
        if choice == "1":
            spinner("Chargement...", delay=0.06, rounds=1000)
        elif choice == "2":
            marquee(">>> Salut ! Ceci est une annonce en défilement <<<", speed=0.03, loops=999)
        elif choice == "3":
            bouncing(" <3 ", speed=0.02, loops=999)
        elif choice == "4":
            wave("WAVEEE", amplitude=2, wavelength=3, speed=0.05, cycles=999)
        elif choice == "5":
            while True:
                typing("Tape... (Ctrl+C pour sortir)", speed=0.03)
                time.sleep(0.8)
        else:
            demo_all()
    except KeyboardInterrupt:
        print("\nBye 👋")
