import { Observable, of, from, interval, throwError } from 'rxjs';
import { map, filter, catchError, switchMap, take, tap } from 'rxjs/operators';

// Mock function to fetch stock prices (simulates API call)
const fetchStockPrice = (ticker: string): Observable<number> => {
    return new Observable<number>((observer) => {
        const intervalId = setInterval(() => {
            if (Math.random() < 0.1) { // Simulating an error 10% of the time
                observer.error(`Error fetching stock price for ${ticker}`);
            } else {
                const price = parseFloat((Math.random() * 1000).toFixed(2));
                observer.next(price);
            }
        }, 1000);

        return () => {
            clearInterval(intervalId);
            console.log(`Stopped fetching prices for ${ticker}`);
        };
    });
};

// Example usage: Tracking stock price updates
const stockTicker = 'AAPL';
const stockPrice$ = fetchStockPrice(stockTicker).pipe(
    map(price => ({ ticker: stockTicker, price })),  // Transform data
    filter(data => data.price > 500), // Only keep prices above 500
    tap(data => console.log(`Price update:`, data)), // Side effect: Logging
    catchError(err => {
        console.error(err);
        return of({ ticker: stockTicker, price: null }); // Fallback observable
    })
);

// Subscribe to the stock price updates
const subscription = stockPrice$.subscribe({
    next: data => console.log(`Subscriber received:`, data),
    error: err => console.error(`Subscription error:`, err),
    complete: () => console.log('Stream complete'),
});

// Automatically unsubscribe after 10 seconds
setTimeout(() => {
    subscription.unsubscribe();
    console.log('Unsubscribed from stock price updates.');
}, 10000);
---
class EnforceAttrsMeta(type):
    """
    Metaclass that enforces the presence of specific attributes in a class
    and automatically decorates methods with a logging wrapper.
    """
    
    required_attributes = ['name', 'version']

    def __new__(cls, name, bases, class_dict):
        """
        Create a new class with enforced attributes and method logging.

        :param name: Name of the class being created.
        :param bases: Tuple of base classes.
        :param class_dict: Dictionary of attributes and methods of the class.
        :return: Newly created class object.
        """
        # Ensure required attributes exist
        for attr in cls.required_attributes:
            if attr not in class_dict:
                raise TypeError(f"Class '{name}' is missing required attribute '{attr}'")

        # Wrap all methods in a logging decorator
        for key, value in class_dict.items():
            if callable(value):  # Check if it's a method
                class_dict[key] = cls.log_calls(value)

        return super().__new__(cls, name, bases, class_dict)

    @staticmethod
    def log_calls(func):
        """
        Decorator that logs method calls and arguments.

        :param func: Function to be wrapped.
        :return: Wrapped function with logging.
        """
        def wrapper(*args, **kwargs):
            print(f"Calling {func.__name__} with args={args} kwargs={kwargs}")
            result = func(*args, **kwargs)
            print(f"{func.__name__} returned {result}")
            return result
        return wrapper


class PluginBase(metaclass=EnforceAttrsMeta):
    """
    Base class for plugins that enforces required attributes and logging.
    """
    name = "BasePlugin"
    version = "1.0"

    def run(self, data):
        """
        Process the input data.

        :param data: The data to be processed.
        :return: Processed result.
        """
        return f"Processed {data}"


class CustomPlugin(PluginBase):
    """
    Custom plugin that extends PluginBase and adheres to enforced rules.
    """
    name = "CustomPlugin"
    version = "2.0"

    def run(self, data):
        """
        Custom processing logic.

        :param data: The data to process.
        :return: Modified data.
        """
        return f"Custom processing of {data}"


# Uncommenting the following class definition will raise a TypeError
# because 'version' attribute is missing.
# class InvalidPlugin(PluginBase):
#     name = "InvalidPlugin"


if __name__ == "__main__":
    # Instantiate and use the plugin
    plugin = CustomPlugin()
    print(plugin.run("example data"))
---
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Click the Box Game</title>
    <style>
        body {
            text-align: center;
            font-family: Arial, sans-serif;
        }
        #game-container {
            position: relative;
            width: 300px;
            height: 300px;
            margin: 20px auto;
            border: 2px solid black;
            overflow: hidden;
        }
        #target {
            width: 50px;
            height: 50px;
            background-color: red;
            position: absolute;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <h1>Click the Box!</h1>
    <p>Score: <span id="score">0</span></p>
    <div id="game-container">
        <div id="target"></div>
    </div>
    <script>
        let score = 0;
        const target = document.getElementById("target");
        const scoreDisplay = document.getElementById("score");
        const container = document.getElementById("game-container");
        
        function moveTarget() {
            const maxX = container.clientWidth - target.clientWidth;
            const maxY = container.clientHeight - target.clientHeight;
            target.style.left = Math.random() * maxX + "px";
            target.style.top = Math.random() * maxY + "px";
        }
        
        target.addEventListener("click", function() {
            score++;
            scoreDisplay.textContent = score;
            moveTarget();
        });
        
        moveTarget();
    </script>
</body>
</html>
