# SPEEDots Security Launcher - Phase 1 Hybrid Infrastructure
# Main Launcher: Python | Game Engine: C# Integration Ready

import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3
import mysql.connector
import threading
import time
import hashlib
import subprocess
import os
import json
from datetime import datetime, timedelta
from typing import Optional, Dict, Any
import requests

class DatabaseManager:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
    
    def __init__(self):
        if hasattr(self, 'initialized'):
            return
        self.initialized = True
        self.local_db = None
        self.remote_config = {
            'host': 'localhost',
            'user': 'speedots',
            'password': 'secure123',
            'database': 'reservesphp'
        }
        self.sync_thread = None
        self.running = True
        
    def initialize(self):
        self.init_local_db()
        self.start_sync_timer()
        
    def init_local_db(self):
        self.local_db = sqlite3.connect('speedots_local.db', check_same_thread=False)
        self.local_db.row_factory = sqlite3.Row
        cursor = self.local_db.cursor()
        
        tables = [
            '''CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                username TEXT UNIQUE NOT NULL,
                password_hash TEXT NOT NULL,
                email TEXT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                last_sync TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )''',
            
            '''CREATE TABLE IF NOT EXISTS games (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                title TEXT NOT NULL,
                developer TEXT,
                price REAL DEFAULT 0,
                reserves_price INTEGER DEFAULT 0,
                owned BOOLEAN DEFAULT 0,
                installed BOOLEAN DEFAULT 0,
                hours_played REAL DEFAULT 0,
                last_played TIMESTAMP,
                trust_score REAL DEFAULT 0,
                download_count INTEGER DEFAULT 0,
                last_sync TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )''',
            
            '''CREATE TABLE IF NOT EXISTS applications (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                title TEXT NOT NULL,
                developer TEXT,
                price REAL DEFAULT 0,
                reserves_price INTEGER DEFAULT 0,
                owned BOOLEAN DEFAULT 0,
                installed BOOLEAN DEFAULT 0,
                trust_score REAL DEFAULT 0,
                virus_scan_status TEXT DEFAULT 'pending',
                download_count INTEGER DEFAULT 0,
                last_sync TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )''',
            
            '''CREATE TABLE IF NOT EXISTS reserves (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id INTEGER,
                amount INTEGER DEFAULT 0,
                last_transaction TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY(user_id) REFERENCES users(id)
            )''',
            
            '''CREATE TABLE IF NOT EXISTS achievements (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id INTEGER,
                game_id INTEGER,
                achievement_name TEXT,
                unlocked_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY(user_id) REFERENCES users(id)
            )''',
            
            '''CREATE TABLE IF NOT EXISTS comments (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                item_id INTEGER,
                item_type TEXT,
                user_id INTEGER,
                comment_text TEXT,
                posted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY(user_id) REFERENCES users(id)
            )''',
            
            '''CREATE TABLE IF NOT EXISTS trust_votes (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                item_id INTEGER,
                item_type TEXT,
                user_id INTEGER,
                vote_value INTEGER,
                voted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY(user_id) REFERENCES users(id)
            )'''
        ]
        
        for sql in tables:
            cursor.execute(sql)
        
        self.local_db.commit()
        
    def start_sync_timer(self):
        def sync_worker():
            while self.running:
                time.sleep(10)  # 10-second sync interval
                self.sync_databases()
                
        self.sync_thread = threading.Thread(target=sync_worker, daemon=True)
        self.sync_thread.start()
        
    def sync_databases(self):
        try:
            cursor = self.local_db.cursor()
            cursor.execute('''
                SELECT * FROM users 
                WHERE last_sync > datetime('now', '-10 seconds')
            ''')
            
            updated_users = cursor.fetchall()
            
            if updated_users:
                remote_conn = mysql.connector.connect(**self.remote_config)
                remote_cursor = remote_conn.cursor()
                
                for user in updated_users:
                    # Get user's reserves
                    cursor.execute('SELECT amount FROM reserves WHERE user_id = ?', (user['id'],))
                    reserves = cursor.fetchone()
                    reserves_amount = reserves['amount'] if reserves else 0
                    
                    # Sync to MySQL
                    sync_query = '''
                        INSERT INTO members (username, email, reserves, last_sync) 
                        VALUES (%s, %s, %s, NOW())
                        ON DUPLICATE KEY UPDATE 
                        reserves = %s, last_sync = NOW()
                    '''
                    remote_cursor.execute(sync_query, (
                        user['username'], user['email'], reserves_amount, reserves_amount
                    ))
                
                remote_conn.commit()
                remote_conn.close()
                
        except Exception as e:
            print(f"Sync error: {e}")
            
    def execute_local(self, query, params=None):
        cursor = self.local_db.cursor()
        if params:
            cursor.execute(query, params)
        else:
            cursor.execute(query)
        self.local_db.commit()
        return cursor
        
    def close(self):
        self.running = False
        if self.local_db:
            self.local_db.close()

class UserSession:
    def __init__(self):
        self.user_id = None
        self.username = None
        self.authenticated = False
        
    async def authenticate(self, username: str, password: str) -> bool:
        password_hash = self.compute_hash(password)
        db = DatabaseManager()
        
        cursor = db.execute_local(
            'SELECT id FROM users WHERE username = ? AND password_hash = ?',
            (username, password_hash)
        )
        
        result = cursor.fetchone()
        
        if result:
            self.user_id = result[0]
            self.username = username
            self.authenticated = True
            return True
            
        return False
        
    def compute_hash(self, password: str) -> str:
        salt = "speedots_salt"
        return hashlib.sha256((password + salt).encode()).hexdigest()
        
    def logout(self):
        self.user_id = None
        self.username = None
        self.authenticated = False

class SecurityManager:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
        
    def scan_file(self, filepath: str) -> bool:
        # Integrate with actual antivirus API here
        # For now, simulate scan
        return True
        
    def verify_digital_signature(self, filepath: str) -> bool:
        # Implement digital signature verification
        return True
        
    def record_trust_vote(self, item_id: int, item_type: str, user_id: int, vote: int):
        db = DatabaseManager()
        db.execute_local('''
            INSERT INTO trust_votes (item_id, item_type, user_id, vote_value)
            VALUES (?, ?, ?, ?)
        ''', (item_id, item_type, user_id, vote))

class SettingsManager:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
        
    def __init__(self):
        if hasattr(self, 'initialized'):
            return
        self.initialized = True
        self.settings = {
            'custom_ide_path': '',
            'blender_path': '',
            'projects_folder': 'C:\\SPEEDots\\Projects',
            'enable_animations': True,
            'animation_speed': 500,
            'csharp_engine_path': 'C:\\SPEEDots\\GameEngine\\SpeedotsEngine.exe'
        }
        self.load_settings()
        
    def load_settings(self):
        try:
            if os.path.exists('speedots_settings.json'):
                with open('speedots_settings.json', 'r') as f:
                    saved_settings = json.load(f)
                    self.settings.update(saved_settings)
        except Exception as e:
            print(f"Settings load error: {e}")
            
    def save_settings(self):
        try:
            with open('speedots_settings.json', 'w') as f:
                json.dump(self.settings, f, indent=2)
        except Exception as e:
            print(f"Settings save error: {e}")
            
    def get(self, key: str) -> Any:
        return self.settings.get(key)
        
    def set(self, key: str, value: Any):
        self.settings[key] = value
        self.save_settings()

class GameEngineInterface:
    """Interface to C# Game Engine Component"""
    
    def __init__(self):
        self.settings = SettingsManager()
        self.engine_path = self.settings.get('csharp_engine_path')
        
    def launch_engine(self, project_path: str = None):
        """Launch the C# Game Engine"""
        try:
            cmd = [self.engine_path]
            if project_path:
                cmd.append(f'--project="{project_path}"')
                
            subprocess.Popen(cmd)
            return True
        except Exception as e:
            print(f"Engine launch error: {e}")
            return False
            
    def create_project(self, project_name: str, project_type: str = "game"):
        """Create new project via C# engine"""
        projects_folder = self.settings.get('projects_folder')
        project_path = os.path.join(projects_folder, project_name)
        
        try:
            os.makedirs(project_path, exist_ok=True)
            
            # Create project structure
            folders = ['assets', 'models', 'scripts', 'scenes', 'textures']
            for folder in folders:
                os.makedirs(os.path.join(project_path, folder), exist_ok=True)
                
            # Create project file
            project_config = {
                'name': project_name,
                'type': project_type,
                'created': datetime.now().isoformat(),
                'engine_version': '1.0'
            }
            
            with open(os.path.join(project_path, 'project.json'), 'w') as f:
                json.dump(project_config, f, indent=2)
                
            return project_path
        except Exception as e:
            print(f"Project creation error: {e}")
            return None

class ThemeManager:
    def __init__(self):
        self.colors = {
            'bg_primary': '#1a1f28',
            'bg_secondary': '#252a35',
            'accent': '#7850c8',
            'secondary_accent': '#5064b4',
            'text_primary': '#f0f0ff',
            'text_secondary': '#c0c0d0',
            'success': '#50c878',
            'warning': '#ffd700',
            'error': '#ff6b6b'
        }
        
    def apply_theme(self, widget, style_type='default'):
        if style_type == 'primary':
            widget.configure(bg=self.colors['bg_primary'], fg=self.colors['text_primary'])
        elif style_type == 'secondary':
            widget.configure(bg=self.colors['bg_secondary'], fg=self.colors['text_secondary'])
        elif style_type == 'accent':
            widget.configure(bg=self.colors['accent'], fg=self.colors['text_primary'])

class MainApplication:
    def __init__(self):
        self.root = tk.Tk()
        self.session = UserSession()
        self.theme = ThemeManager()
        self.engine_interface = GameEngineInterface()
        self.current_panel = None
        
        self.setup_main_window()
        self.create_login_panel()
        
    def setup_main_window(self):
        self.root.title("SPEEDots Security Launcher")
        self.root.geometry("1200x800")
        self.root.configure(bg='#1a1f28')
        self.root.state('zoomed')  # Maximize window
        
    def create_login_panel(self):
        self.login_frame = tk.Frame(self.root, bg='#1a1f28')
        self.login_frame.pack(fill='both', expand=True)
        
        # Login box with gradient effect simulation
        login_box = tk.Frame(self.login_frame, bg='#2d3442', relief='raised', bd=2)
        login_box.place(relx=0.5, rely=0.5, anchor='center', width=400, height=300)
        
        # Title
        title_label = tk.Label(login_box, text="SPEEDots Security Launcher", 
                              bg='#2d3442', fg='#f0f0ff', font=('Arial', 16, 'bold'))
        title_label.pack(pady=20)
        
        # Username entry
        tk.Label(login_box, text="Username:", bg='#2d3442', fg='#c0c0d0').pack(pady=(10,5))
        self.username_entry = tk.Entry(login_box, bg='#3c4650', fg='white', 
                                      insertbackground='white', width=30)
        self.username_entry.pack(pady=5)
        
        # Password entry
        tk.Label(login_box, text="Password:", bg='#2d3442', fg='#c0c0d0').pack(pady=(10,5))
        self.password_entry = tk.Entry(login_box, bg='#3c4650', fg='white', 
                                      insertbackground='white', width=30, show='*')
        self.password_entry.pack(pady=5)
        
        # Login button
        login_btn = tk.Button(login_box, text="LOGIN", bg='#7850c8', fg='white',
                             font=('Arial', 12, 'bold'), width=15,
                             command=self.handle_login)
        login_btn.pack(pady=20)
        
        # Bind Enter key to login
        self.root.bind('<Return>', lambda e: self.handle_login())
        
    def handle_login(self):
        username = self.username_entry.get()
        password = self.password_entry.get()
        
        if not username or not password:
            messagebox.showerror("Error", "Please enter username and password")
            return
            
        # Simulate authentication (in real app, this would be async)
        password_hash = self.session.compute_hash(password)
        
        # For demo, create user if doesn't exist
        db = DatabaseManager()
        cursor = db.execute_local(
            'SELECT id FROM users WHERE username = ?', (username,)
        )
        
        if not cursor.fetchone():
            db.execute_local(
                'INSERT INTO users (username, password_hash, email) VALUES (?, ?, ?)',
                (username, password_hash, f"{username}@speedots.com")
            )
            
        if self.session.authenticate(username, password):
            self.show_loading_screen()
        else:
            messagebox.showerror("Error", "Invalid credentials")
            
    def show_loading_screen(self):
        self.login_frame.destroy()
        
        self.loading_frame = tk.Frame(self.root, bg='#1a1f28')
        self.loading_frame.pack(fill='both', expand=True)
        
        # Loading label
        loading_label = tk.Label(self.loading_frame, text="Loading SPEEDots...", 
                               bg='#1a1f28', fg='#f0f0ff', font=('Arial', 18))
        loading_label.pack(expand=True)
        
        # Emblem marquee simulation
        emblem_frame = tk.Frame(self.loading_frame, bg='#2d3442', height=100)
        emblem_frame.pack(fill='x', padx=50, pady=20)
        
        tk.Label(emblem_frame, text="🏆 🎮 ⭐ 🔧 💎", bg='#2d3442', fg='#7850c8', 
                font=('Arial', 24)).pack(expand=True)
        
        # Simulate loading delay then show main interface
        self.root.after(2000, self.show_main_interface)
        
    def show_main_interface(self):
        self.loading_frame.destroy()
        
        # Create main interface with tabs
        self.main_frame = tk.Frame(self.root, bg='#1a1f28')
        self.main_frame.pack(fill='both', expand=True)
        
        # Create notebook (tabs)
        style = ttk.Style()
        style.theme_use('clam')
        style.configure('TNotebook', background='#1e252f')
        style.configure('TNotebook.Tab', background='#2d3442', foreground='#c0c0d0')
        style.map('TNotebook.Tab', background=[('selected', '#7850c8')])
        
        self.notebook = ttk.Notebook(self.main_frame)
        self.notebook.pack(fill='both', expand=True, padx=5, pady=5)
        
        # Create all tabs
        self.create_tabs()
        
        # Add logout button
        logout_btn = tk.Button(self.main_frame, text="Logout", bg='#ff6b6b', fg='white',
                              command=self.logout)
        logout_btn.pack(side='bottom', anchor='se', padx=10, pady=10)
        
    def create_tabs(self):
        tabs = [
            ("Front", FrontPageTab),
            ("Games", GamesTab),
            ("Applications", ApplicationsTab),
            ("Store", StoreTab),
            ("GameEngine", GameEngineTab),
            ("Publishing", PublishingTab),
            ("Messaging", MessagingTab),
            ("VCS", VCSTab),
            ("Profile", ProfileTab),
            ("3DModelling", ModellingTab),
            ("Paint.C++", PaintTab)
        ]
        
        for tab_name, tab_class in tabs:
            tab_frame = tab_class(self.notebook, self)
            self.notebook.add(tab_frame, text=tab_name)
            
    def logout(self):
        self.session.logout()
        self.main_frame.destroy()
        self.create_login_panel()

# Base Tab Class
class BaseTab(tk.Frame):
    def __init__(self, parent, app):
        super().__init__(parent, bg='#1e252f')
        self.app = app
        self.theme = app.theme
        self.setup_tab()
        
    def setup_tab(self):
        # Override in subclasses
        tk.Label(self, text=f"{self.__class__.__name__} - Coming Soon!", 
                bg='#1e252f', fg='#c0c0d0', font=('Arial', 16)).pack(expand=True)

# Tab Classes (Stubs for now - will be implemented in next phases)
class FrontPageTab(BaseTab):
    def setup_tab(self):
        tk.Label(self, text="Twitter-style Feed", bg='#1e252f', fg='#f0f0ff', 
                font=('Arial', 18, 'bold')).pack(pady=20)
        tk.Label(self, text="Game/App releases, comments, download stats", 
                bg='#1e252f', fg='#c0c0d0').pack()

class GamesTab(BaseTab):
    def setup_tab(self):
        tk.Label(self, text="Games Library", bg='#1e252f', fg='#f0f0ff', 
                font=('Arial', 18, 'bold')).pack(pady=20)
        tk.Label(self, text="Steam-like game management", 
                bg='#1e252f', fg='#c0c0d0').pack()

class ApplicationsTab(BaseTab):
    def setup_tab(self):
        tk.Label(self, text="Applications Library", bg='#1e252f', fg='#f0f0ff', 
                font=('Arial', 18, 'bold')).pack(pady=20)
        tk.Label(self, text="Trust scoring and virus scan results", 
                bg='#1e252f', fg='#c0c0d0').pack()

class StoreTab(BaseTab):
    def setup_tab(self):
        tk.Label(self, text="SPEEDots Store", bg='#1e252f', fg='#f0f0ff', 
                font=('Arial', 18, 'bold')).pack(pady=20)
        tk.Label(self, text="Reserves currency and emblem shop", 
                bg='#1e252f', fg='#c0c0d0').pack()

class GameEngineTab(BaseTab):
    def setup_tab(self):
        tk.Label(self, text="Game Engine (C# Integration)", bg='#1e252f', fg='#f0f0ff', 
                font=('Arial', 18, 'bold')).pack(pady=20)
        
        # Engine launch button
        launch_btn = tk.Button(self, text="Launch Game Engine", bg='#7850c8', fg='white',
                              font=('Arial', 12, 'bold'),
                              command=lambda: self.app.engine_interface.launch_engine())
        launch_btn.pack(pady=10)
        
        # Create project button
        create_btn = tk.Button(self, text="Create New Project", bg='#50c878', fg='white',
                              font=('Arial', 12, 'bold'),
                              command=self.create_project_dialog)
        create_btn.pack(pady=5)
        
    def create_project_dialog(self):
        dialog = tk.Toplevel(self)
        dialog.title("Create New Project")
        dialog.geometry("300x150")
        dialog.configure(bg='#2d3442')
        
        tk.Label(dialog, text="Project Name:", bg='#2d3442', fg='#c0c0d0').pack(pady=10)
        name_entry = tk.Entry(dialog, bg='#3c4650', fg='white')
        name_entry.pack(pady=5)
        
        def create():
            name = name_entry.get()
            if name:
                path = self.app.engine_interface.create_project(name)
                if path:
                    messagebox.showinfo("Success", f"Project created at: {path}")
                    dialog.destroy()
                else:
                    messagebox.showerror("Error", "Failed to create project")
            
        tk.Button(dialog, text="Create", bg='#7850c8', fg='white',
                 command=create).pack(pady=10)

class PublishingTab(BaseTab):
    def setup_tab(self):
        tk.Label(self, text="Publishing Platform", bg='#1e252f', fg='#f0f0ff', 
                font=('Arial', 18, 'bold')).pack(pady=20)
        tk.Label(self, text="Virus scanning, approval system, PayPal integration", 
                bg='#1e252f', fg='#c0c0d0').pack()

class MessagingTab(BaseTab):
    def setup_tab(self):
        tk.Label(self, text="FreeChat Integration", bg='#1e252f', fg='#f0f0ff', 
                font=('Arial', 18, 'bold')).pack(pady=20)
        tk.Label(self, text="Community messaging and friends", 
                bg='#1e252f', fg='#c0c0d0').pack()

class VCSTab(BaseTab):
    def setup_tab(self):
        tk.Label(self, text="Virtual Currency System", bg='#1e252f', fg='#f0f0ff', 
                font=('Arial', 18, 'bold')).pack(pady=20)
        tk.Label(self, text="ATM-style reserves management", 
                bg='#1e252f', fg='#c0c0d0').pack()

class ProfileTab(BaseTab):
    def setup_tab(self):
        tk.Label(self, text="User Profile", bg='#1e252f', fg='#f0f0ff', 
                font=('Arial', 18, 'bold')).pack(pady=20)
        tk.Label(self, text="Achievements, stats, friends", 
                bg='#1e252f', fg='#c0c0d0').pack()

class ModellingTab(BaseTab):
    def setup_tab(self):
        tk.Label(self, text="3D Modeller", bg='#1e252f', fg='#f0f0ff', 
                font=('Arial', 18, 'bold')).pack(pady=20)
        tk.Label(self, text="Maya controls, Blender integration", 
                bg='#1e252f', fg='#c0c0d0').pack()

class PaintTab(BaseTab):
    def setup_tab(self):
        tk.Label(self, text="Paint.C++ Image Editor", bg='#1e252f', fg='#f0f0ff', 
                font=('Arial', 18, 'bold')).pack(pady=20)
        tk.Label(self, text="UV mapping and texture creation", 
                bg='#1e252f', fg='#c0c0d0').pack()

# Main Entry Point
def main():
    # Initialize core systems
    db = DatabaseManager()
    db.initialize()
    
    # Create and run main application
    app = MainApplication()
    
    try:
        app.root.mainloop()
    finally:
        db.close()

if __name__ == "__main__":
    main()