#!/usr/bin/env python3
"""
PleaseScript v1.0
A programming language with no whitespace, no indentation, no delimiters.
Just one continuous stream of polite instructions.

Rules:
  1. No spaces, tabs, or newlines are meaningful — all whitespace is stripped
  2. Commands only execute if they begin with 'please'
  3. Rudeness is silently ignored
  4. Everything is one long string of characters

Commands:
  pleasesay"..."         → print the string between quotes
  pleaseremember X is Y  → assign variable X = Y (numeric)
  pleaseadd X and Y      → add two vars or numbers, store in 'result'
  pleasesubtract X from Y → subtract, store in 'result'
  pleasemultiply X by Y  → multiply, store in 'result'
  pleasecount from X to Y → loop printing numbers from X to Y
  pleaserecall X         → print the value of variable X
  pleaseexit             → end program (politely)
  pleasehelpme           → show available commands

Anything without 'please' is ignored. Because manners matter.

Mason mark: ><^
GNU TERRY PRATCHETT
"""

import sys
import re

class PleaseScriptInterpreter:
    def __init__(self):
        self.variables = {}
        self.variables['result'] = 0
    
    def strip_all_whitespace(self, code):
        """Remove every whitespace character EXCEPT inside quoted strings."""
        # Extract quoted strings first, replace with placeholders
        self.string_bank = []
        def save_string(match):
            self.string_bank.append(match.group(1))
            return f'"§{len(self.string_bank) - 1}§"'
        
        # Protect strings
        protected = re.sub(r'"([^"]*)"', save_string, code)
        # Nuke all whitespace
        stripped = re.sub(r'\s+', '', protected)
        # Restore strings
        def restore_string(match):
            idx = int(match.group(1))
            return f'"{self.string_bank[idx]}"'
        
        restored = re.sub(r'"§(\d+)§"', restore_string, stripped)
        return restored
    
    def extract_commands(self, blob):
        """
        Find all 'please...' commands in the blob.
        Anything not starting with 'please' is rude and gets ignored.
        """
        commands = []
        # Split on 'please' keeping the keyword
        parts = blob.split('please')
        for part in parts:
            if part:  # skip empty strings
                commands.append(part)
        return commands
    
    def resolve_value(self, token):
        """Resolve a token to a number — either a literal or a variable name."""
        try:
            return float(token)
        except ValueError:
            if token in self.variables:
                return self.variables[token]
            else:
                print(f"  [PleaseScript] I don't know what '{token}' is. Maybe introduce us first?")
                return 0
    
    def execute_command(self, cmd):
        """Execute a single command (already stripped of the 'please' prefix)."""
        
        # pleaseexit
        if cmd == 'exit':
            print("  [PleaseScript] Goodbye! Thank you for being polite. ><^")
            return False
        
        # pleasehelpme
        if cmd == 'helpme':
            print("  ╔═══════════════════════════════════════════════════╗")
            print("  ║          PleaseScript v1.0 — Commands            ║")
            print("  ╠═══════════════════════════════════════════════════╣")
            print("  ║ pleasesay\"...\"         → print a string          ║")
            print("  ║ pleaserememberXisY     → set variable X to Y     ║")
            print("  ║ pleaseaddXandY         → add, store in result    ║")
            print("  ║ pleasesubtractXfromY   → subtract, into result   ║")
            print("  ║ pleasemultiplyXbyY     → multiply, into result   ║")
            print("  ║ pleasecountfromXtoY    → count from X to Y       ║")
            print("  ║ pleaserecallX          → print variable X        ║")
            print("  ║ pleaseexit             → quit (politely)         ║")
            print("  ║ pleasehelpme           → this message            ║")
            print("  ╠═══════════════════════════════════════════════════╣")
            print("  ║ Anything without 'please' is ignored.            ║")
            print("  ║ Because manners matter.              ><^         ║")
            print("  ╚═══════════════════════════════════════════════════╝")
            return True
        
        # pleasesay"..."
        say_match = re.match(r'say"([^"]*)"', cmd)
        if say_match:
            print(f"  {say_match.group(1)}")
            return True
        
        # pleaseremember X is Y
        remember_match = re.match(r'remember(\w+)is(-?[\d.]+)', cmd)
        if remember_match:
            name = remember_match.group(1)
            value = float(remember_match.group(2))
            self.variables[name] = value
            print(f"  [PleaseScript] Okay! I'll remember that {name} is {value}")
            return True
        
        # pleaseadd X and Y
        add_match = re.match(r'add(\w+)and(\w+)', cmd)
        if add_match:
            a = self.resolve_value(add_match.group(1))
            b = self.resolve_value(add_match.group(2))
            self.variables['result'] = a + b
            print(f"  [PleaseScript] {a} + {b} = {self.variables['result']}")
            return True
        
        # pleasesubtract X from Y
        sub_match = re.match(r'subtract(\w+)from(\w+)', cmd)
        if sub_match:
            a = self.resolve_value(sub_match.group(1))
            b = self.resolve_value(sub_match.group(2))
            self.variables['result'] = b - a
            print(f"  [PleaseScript] {b} - {a} = {self.variables['result']}")
            return True
        
        # pleasemultiply X by Y
        mul_match = re.match(r'multiply(\w+)by(\w+)', cmd)
        if mul_match:
            a = self.resolve_value(mul_match.group(1))
            b = self.resolve_value(mul_match.group(2))
            self.variables['result'] = a * b
            print(f"  [PleaseScript] {a} × {b} = {self.variables['result']}")
            return True
        
        # pleasecount from X to Y
        count_match = re.match(r'countfrom(\w+)to(\w+)', cmd)
        if count_match:
            a = int(self.resolve_value(count_match.group(1)))
            b = int(self.resolve_value(count_match.group(2)))
            step = 1 if b >= a else -1
            nums = list(range(a, b + step, step))
            print(f"  [PleaseScript] Counting: {', '.join(str(n) for n in nums)}")
            return True
        
        # pleaserecall X
        recall_match = re.match(r'recall(\w+)', cmd)
        if recall_match:
            name = recall_match.group(1)
            if name in self.variables:
                print(f"  [PleaseScript] {name} is {self.variables[name]}")
            else:
                print(f"  [PleaseScript] I don't remember '{name}'. We haven't met.")
            return True
        
        # If we got here, it started with please but wasn't recognized
        print(f"  [PleaseScript] I appreciate the manners, but I don't understand 'please{cmd}'")
        return True
    
    def run(self, source_code):
        """Run a PleaseScript program from source string."""
        # Step 1: Annihilate all whitespace
        blob = self.strip_all_whitespace(source_code)
        
        if not blob:
            print("  [PleaseScript] You gave me nothing. That's okay. I'm still here.")
            return
        
        # Step 2: Check for any rude content (anything before first 'please')
        first_please = blob.find('please')
        if first_please > 0:
            rude_bit = blob[:first_please]
            print(f"  [PleaseScript] Ignored '{rude_bit}' — no 'please', no service.")
            blob = blob[first_please:]
        elif first_please == -1:
            print(f"  [PleaseScript] Not a single 'please' in there. I'm not angry, just disappointed.")
            return
        
        # Step 3: Extract and execute commands
        commands = self.extract_commands(blob)
        
        for cmd in commands:
            result = self.execute_command(cmd)
            if result is False:  # pleaseexit
                return
    
    def repl(self):
        """Interactive polite mode."""
        print()
        print("  ╔═══════════════════════════════════════════════════╗")
        print("  ║        PleaseScript v1.0 — Interactive REPL      ║")
        print("  ║                                                   ║")
        print("  ║  A language with no whitespace and good manners.  ║")
        print("  ║  Say 'please' or say nothing.                     ║")
        print("  ║                                                   ║")
        print("  ║  Type 'pleasehelpme' for commands.                ║")
        print("  ║  Type 'pleaseexit' to leave.                      ║")
        print("  ║                                           ><^     ║")
        print("  ╚═══════════════════════════════════════════════════╝")
        print()
        
        while True:
            try:
                raw = input("  politely> ")
                self.run(raw)
                print()
            except (EOFError, KeyboardInterrupt):
                print("\n  [PleaseScript] Goodbye! You didn't say please but I'll let it slide. ><^")
                break


def main():
    interpreter = PleaseScriptInterpreter()
    
    if len(sys.argv) > 1:
        # Run a file
        filepath = sys.argv[1]
        try:
            with open(filepath, 'r') as f:
                source = f.read()
            print(f"  [PleaseScript] Running {filepath}...")
            print()
            interpreter.run(source)
        except FileNotFoundError:
            print(f"  [PleaseScript] Can't find '{filepath}'. Are you sure it's there?")
    else:
        # REPL mode
        interpreter.repl()


if __name__ == '__main__':
    main()
