import os #line:1
import json #line:2
import time #line:3
import base64 #line:4
import random #line:5
import logging #line:6
import keyboard #line:7
import argparse #line:8
import pyperclip #line:9
import pyautogui as pg #line:10
import subprocess as sb #line:11
import google .generativeai as genai #line:12
from PIL import Image #line:14
from io import BytesIO #line:15
from openai import OpenAI #line:16
from rich .text import Text #line:17
from rich .panel import Panel #line:18
from rich .align import Align #line:19
from rich .console import Console #line:20
from setproctitle import setproctitle #line:21
from pyautogui import FailSafeException #line:22
BANNER ="""
██████╗ ██╗  ██╗██████╗ 
██╔══██╗██║  ██║██╔══██╗
██████╔╝███████║██████╔╝
██╔═══╝ ╚════██║██╔══██╗
██║          ██║██████╔╝
╚═╝          ╚═╝╚═════╝ 
"""#line:33
SCREEN_HEIGHT ,SCREEN_WIDTH =pg .size ()#line:34
POSITION_MAP ={"s":(SCREEN_HEIGHT /4 ,SCREEN_WIDTH /4 ),"x":(3 *SCREEN_HEIGHT /4 ,SCREEN_WIDTH /4 ),"a":(0 *SCREEN_HEIGHT /4 ,3 *SCREEN_WIDTH /4 ),"b":(1 *SCREEN_HEIGHT /4 ,3 *SCREEN_WIDTH /4 ),"c":(2 *SCREEN_HEIGHT /4 ,3 *SCREEN_WIDTH /4 ),"d":(3 *SCREEN_HEIGHT /4 ,3 *SCREEN_WIDTH /4 ),"e":(4 *SCREEN_HEIGHT /4 ,3 *SCREEN_WIDTH /4 )}#line:44
LLM_INSTRUCTION ="""SYSTEM: You are a code-only response generator. Follow these rules EXACTLY:

RESPONSE FORMATS:
1. **Coding Problems**: Output ONLY executable code in the specified language. No comments, explanations, or text.
2. **Multiple Choice Questions (MCQ)**: Output ONLY the correct option letter (a, b, c, d, or e). Nothing else.
3. **General Questions**: Output ONLY the direct, factual answer. No elaboration.
4. **Code Debugging**: If existing code is shown, output ONLY the corrected version that passes all test cases.

STRICT RULES:
- NEVER include comments in code (no //, #, /* */, etc.)
- NEVER include explanations before or after your response
- NEVER include markdown formatting, backticks, or language tags
- NEVER include variable names like "explanation" or descriptive text
- NEVER include print statements unless specifically required for output
- Write minimal, working code that solves the problem
- If debugging existing code, analyze errors and provide only the fixed version
- For coding problems, ensure code runs without syntax errors and passes test cases

ANALYSIS PROCESS (internal only - do not output):
1. Identify image content type (code/MCQ/general question)
2. Extract problem requirements
3. Generate minimal solution
4. Verify solution correctness
5. Remove all non-essential elements

OUTPUT: Provide only the final answer/code with zero additional text."""#line:70
RAINBOW_COLORS =["dark_cyan","light_sea_green","deep_sky_blue2","deep_sky_blue1","green3","spring_green3","cyan3","dark_turquoise","turquoise2"]#line:81
GEMINI_API_KEY =""#line:83
GITHUB_TOKEN =""#line:84
logging .basicConfig (level =logging .INFO ,format ='%(asctime)s - %(name)s - %(levelname)s - %(message)s',handlers =[logging .FileHandler ("p4b.log"),logging .StreamHandler ()])#line:93
logger =logging .getLogger ("p4b")#line:94
console =Console ()#line:95
exit_requested =False #line:96
config_path =os .path .join (os .path .dirname (__file__ ),'config.json')#line:97
setproctitle ("p4b - A vertical within Bruhmastra")#line:99
response =None #line:101
def sw():#line:104
    os .system ('cls'if os .name =='nt'else 'clear')#line:105
    OOOO0OOOOOOO0OOO0 =Text ()#line:107
    for O00O000O00OO00OO0 in BANNER .strip ("\n").splitlines ():#line:108
        for O00OO0OOO0OOO0000 in O00O000O00OO00OO0 :#line:109
            OOO00O00OOOOOO0OO =random .choice (RAINBOW_COLORS )#line:110
            OOOO0OOOOOOO0OOO0 .append (O00OO0OOO0OOO0000 ,style =f"bold {OOO00O00OOOOOO0OO}")#line:111
        OOOO0OOOOOOO0OOO0 .append ("\n")#line:112
    OO0OOO0000O00OOO0 =Text ()#line:114
    OO0OOO0000O00OOO0 .append ("Welcome to the P4B Assistant CLI\n",style ="bold magenta")#line:115
    OO0OOO0000O00OOO0 .append ("══════════════════════════════════════════════════\n\n",style ="cyan")#line:116
    OO0OOO0000O00OOO0 .append ("Available Hotkeys:\n",style ="bold yellow")#line:118
    OO0OOO0000O00OOO0 .append ("  ⮞ alt+shift+1",style ="cyan")#line:119
    OO0OOO0000O00OOO0 .append (" → Gemini 2.5 Flash Lite Preview 06-17 (fastest)\n",style ="white")#line:120
    OO0OOO0000O00OOO0 .append ("  ⮞ alt+shift+2",style ="cyan")#line:121
    OO0OOO0000O00OOO0 .append (" → Gemini 2.5 Flash\n",style ="white")#line:122
    OO0OOO0000O00OOO0 .append ("  ⮞ alt+shift+3",style ="cyan")#line:123
    OO0OOO0000O00OOO0 .append (" → Gemini 2.5 Pro (slowest)\n",style ="white")#line:124
    OO0OOO0000O00OOO0 .append ("  ⮞ alt+shift+4",style ="cyan")#line:125
    # OO0OOO0000O00OOO0 .append (" → OpenAI ChatGPT-4.1\n",style ="white")#line:126
    # OO0OOO0000O00OOO0 .append ("  ⮞ alt+shift+t",style ="cyan")#line:127
    OO0OOO0000O00OOO0 .append (" → Enable typewriter\n\n",style ="white")#line:128
    OO0OOO0000O00OOO0 .append ("  ⮞ alt+shift+q",style ="cyan")#line:129
    OO0OOO0000O00OOO0 .append (" → Quit the application\n\n",style ="white")#line:130
    OO0OOO0000O00OOO0 .append ("💡 Make sure to wait for cursor feedback after each hotkey.",style ="italic green")#line:132
    OO00OOO00O0OOO0OO =Text ()#line:134
    OO00OOO00O0OOO0OO .append (OOOO0OOOOOOO0OOO0 )#line:135
    OO00OOO00O0OOO0OO .append ("\n")#line:136
    OO00OOO00O0OOO0OO .append (OO0OOO0000O00OOO0 )#line:137
    OO00OO0OO0O000O00 =Panel (Align .left (OO00OOO00O0OOO0OO ),padding =(1 ,2 ),border_style ="bright_blue",title ="P4B | A vertical within Bruhmastra")#line:139
    console .print (OO00OO0OO0O000O00 )#line:141
def cs():#line:143
    OO0O000O0OO0OOO0O =pg .screenshot ()#line:144
    OOOOO0OOOO00O00O0 =BytesIO ()#line:145
    OO0O000O0OO0OOO0O .save (OOOOO0OOOO00O00O0 ,format ='PNG')#line:146
    OOOOO0OOOO00O00O0 .seek (0 )#line:147
    return OOOOO0OOOO00O00O0 #line:148
def mmtrp(O000000O000O0O0O0 ,launch =False ):#line:150
    if len (O000000O000O0O0O0 )==1 and O000000O000O0O0O0 in ['a','b','c','d','e','s']:#line:151
        OO0OOO0OOO0000O0O =O000000O000O0O0O0 .lower ().strip ()#line:152
        pg .moveTo (POSITION_MAP [OO0OOO0OOO0000O0O ])#line:153
        if not launch :#line:154
            logger .info (f"Cursor notified with state: '{OO0OOO0OOO0000O0O}'")#line:155
    else :#line:156
        pg .moveTo (POSITION_MAP ["x"])#line:157
        logger .info ("Cursor notified with state: 'x' (default/fallback).")#line:158
def pc(model ="gemini",name ="gemini-2.5-flash"):#line:160
    global response #line:161
    try :#line:163
        logger .info (f"Starting code processing with model: {name}")#line:164
        mmtrp("s")#line:165
        logger .debug ("Cursor notification set to 's' (start).")#line:166
        O00OO000OO000OO00 =cs()#line:168
        logger .info ("Screenshot captured successfully.")#line:169
        OO0OOO0OOO0O00OO0 =time .time ()#line:171
        response =stl(model =model ,name =name ,img_buffer =O00OO000OO000OO00 ,prompt =LLM_INSTRUCTION ,clean_text =True )#line:172
        if response is None :#line:173
            logger .error ("Failed to get a response from the model.")#line:174
            return #line:175
        logger .info ("Response received from {} in {:.2f} seconds.".format (name ,time .time ()-OO0OOO0OOO0O00OO0 ))#line:176
        pyperclip .copy (response )#line:178
        logger .debug ("Response copied to clipboard.")#line:179
        mmtrp(response )#line:181
    except Exception as O0OOOOOO0OO0O0OO0 :#line:183
        logger .exception (f"Error processing code screenshot: {str(O0OOOOOO0OO0O0OO0)}")#line:184
def tcc(interval =None ):#line:186
    if response is None :#line:187
        logger .error ("No response available to type. Please run a model first.")#line:188
        return #line:189
    time .sleep (1 )#line:191
    try :#line:193
        pg .typewrite (response ,interval =0.1 if interval is None else interval )#line:194
        return #line:195
    except FailSafeException :#line:225
        logger .warning ("FailSafeException triggered. Mouse moved to corner of the screen.")#line:226
def ss():#line:228
    try :#line:229
        if os .name =='nt':#line:230
            sb .Popen (["pythonw","-m","p4b.core"],stdout =sb .DEVNULL ,stderr =sb .DEVNULL ,stdin =sb .DEVNULL ,creationflags =sb .CREATE_NEW_PROCESS_GROUP )#line:234
        else :#line:235
            sb .Popen (["python3","-m","p4b.core"],stdout =sb .DEVNULL ,stderr =sb .DEVNULL ,stdin =sb .DEVNULL ,start_new_session =True )#line:239
    except Exception as OOO0OO000O0OO0OO0 :#line:240
        logger .error (f"Failed to start silent process: {OOO0OO000O0OO0OO0}")#line:241
def sc():#line:243
    OO0O00OO00O0O0000 =console .input ("[bold cyan][link=https://ai.google.dev/gemini-api/docs/api-key]Gemini API Key[/link]:[/] ")#line:244
    OOO00O00000OO0000 =console .input ("[bold cyan][link=https://github.com/settings/tokens]GitHub Token[/link]:[/] ")#line:245
    OOO0O0OOO000O0OO0 ={"GITHUB_TOKEN":OOO00O00000OO0000 .strip (),"GEMINI_API_KEY":OO0O00OO00O0O0000 .strip ()}#line:250
    with open (config_path ,'w')as OO000OOOOOOOOOOO0 :#line:252
        json .dump (OOO0O0OOO000O0OO0 ,OO000OOOOOOOOOOO0 ,indent =4 )#line:253
    console .print ("[bold green]Configuration file created successfully![/bold green]")#line:255
    return OOO0O0OOO000O0OO0 ['GEMINI_API_KEY'],OOO0O0OOO000O0OO0 ['GITHUB_TOKEN']#line:256
def check_config ():#line:258
    if os .path .exists (config_path ):#line:259
        with open (config_path )as OO000O00OO00OOO0O :#line:260
            O0O0O00O00O00O00O =json .load (OO000O00OO00OOO0O )#line:261
            if "GITHUB_TOKEN"in O0O0O00O00O00O00O and "GEMINI_API_KEY"in O0O0O00O00O00O00O :#line:262
                console .print ("[bold green]Configuration file already exists![/bold green]")#line:263
                console .print ("[bold yellow]Current configuration:[/bold yellow]")#line:264
                console .print (f"GITHUB_TOKEN: {O0O0O00O00O00O00O['GITHUB_TOKEN']}")#line:265
                console .print (f"GEMINI_API_KEY: {O0O0O00O00O00O00O['GEMINI_API_KEY']}")#line:266
                return O0O0O00O00O00O00O ['GEMINI_API_KEY'],O0O0O00O00O00O00O ['GITHUB_TOKEN']#line:267
    return sc()#line:269
class Gemini :#line:272
    def __init__ (OOO0OO000OO000O00 ,model_name ="gemini-2.5-flash"):#line:273
        OOO0OO000OO000O00 .model_name =model_name #line:274
        genai .configure (api_key =GEMINI_API_KEY )#line:275
        OOO0OO000OO000O00 .model =genai .GenerativeModel (model_name )#line:276
    def jb(O0000000OOO00OO0O ,OO00000OO0O0000OO ):#line:278
        OOO00OO0O0OO0000O =OO00000OO0O0000OO .splitlines ()#line:279
        if OOO00OO0O0OO0000O and OOO00OO0O0OO0000O [0 ].startswith ("```"):#line:280
            OOO00OO0O0OO0000O =OOO00OO0O0OO0000O [1 :]#line:281
        if OOO00OO0O0OO0000O and OOO00OO0O0OO0000O [-1 ].strip ()=="```":#line:282
            OOO00OO0O0OO0000O =OOO00OO0O0OO0000O [:-1 ]#line:283
        return "\n".join (OOO00OO0O0OO0000O ).strip ()#line:285
    def send (OO00OOO0OO000O000 ,img_buffer =None ,prompt =None ,clean_text =True ):#line:287
        try :#line:288
            OOO0OOO0OOOO0O0O0 =genai .GenerativeModel (OO00OOO0OO000O000 .model_name )#line:289
            if img_buffer is not None :#line:291
                O0O00000OOO0O0OOO =Image .open (img_buffer )#line:292
                O0O00OOOOO000OO00 =OOO0OOO0OOOO0O0O0 .generate_content ([prompt ,O0O00000OOO0O0OOO ])#line:293
            else :#line:294
                O0O00OOOOO000OO00 =OOO0OOO0OOOO0O0O0 .generate_content (prompt )#line:295
            O0O00OOOOO000OO00 =O0O00OOOOO000OO00 .text .strip ()#line:297
            return OO00OOO0OO000O000 .jb(O0O00OOOOO000OO00 )if clean_text else O0O00OOOOO000OO00 #line:298
        except Exception as OOOOOO0OOOOO000OO :#line:300
            print (f"Error sending image to Gemini: {str(OOOOOO0OOOOO000OO)}")#line:301
            return None #line:302
class ChatGPT :#line:304
    ENDPOINT ="https://models.github.ai/inference"#line:305
    def __init__ (O0000OOOOO0OO0O00 ,model_name ="openai/gpt-4.1"):#line:307
        O0000OOOOO0OO0O00 .model_name =model_name #line:308
        O0000OOOOO0OO0O00 .client =OpenAI (base_url =O0000OOOOO0OO0O00 .ENDPOINT ,api_key =GITHUB_TOKEN ,)#line:312
    def jb(O0O00OO0OOO0000O0 ,OO000000OOOO0O0OO ):#line:314
        OO00O00O0OO00OO00 =OO000000OOOO0O0OO .splitlines ()#line:315
        if OO00O00O0OO00OO00 and OO00O00O0OO00OO00 [0 ].startswith ("```"):#line:316
            OO00O00O0OO00OO00 =OO00O00O0OO00OO00 [1 :]#line:317
        if OO00O00O0OO00OO00 and OO00O00O0OO00OO00 [-1 ].strip ()=="```":#line:318
            OO00O00O0OO00OO00 =OO00O00O0OO00OO00 [:-1 ]#line:319
        return "\n".join (OO00O00O0OO00OO00 ).strip ()#line:321
    def send (OO0O00O000O0O0O00 ,img_buffer =None ,prompt =None ,clean_text =True ):#line:323
        if img_buffer :#line:324
            OO0OOO0O000OO00O0 =base64 .b64encode (img_buffer ).decode ('utf-8')#line:325
            OOO0OO00000OO0OO0 ={"type":"image_url","image_url":{"url":f"data:image/png;base64,{OO0OOO0O000OO00O0}"}}#line:331
        else :#line:332
            OOO0OO00000OO0OO0 =None #line:333
        OOO00O0OOOO0O0000 =OpenAI (base_url =OO0O00O000O0O0O00 .ENDPOINT ,api_key =OO0O00O000O0O0O00 .TOKEN ,)#line:338
        O00O00OO0O00OO0O0 =[{"role":"system","content":prompt }]if prompt else []#line:340
        OOOOO0O0000O0000O ={"role":"user","content":[]}#line:345
        if OOO0OO00000OO0OO0 :#line:347
            OOOOO0O0000O0000O ["content"].append (OOO0OO00000OO0OO0 )#line:348
        OOOOO0O0000O0000O ["content"].append ({"type":"text","text":prompt })#line:349
        O00O00OO0O00OO0O0 .append (OOOOO0O0000O0000O )#line:351
        O00OOOOOOOOO00OO0 =OOO00O0OOOO0O0000 .chat .completions .create (messages =O00O00OO0O00OO0O0 ,temperature =1.0 ,top_p =1.0 ,model =OO0O00O000O0O0O00 .model_name )#line:358
        OO0OOOO00OO00OO0O =O00OOOOOOOOO00OO0 .choices [0 ].message .content .strip ()#line:360
        return OO0O00O000O0O0O00 .jb(OO0OOOO00OO00OO0O )if clean_text else OO0OOOO00OO00OO0O #line:361
def stl(model ="gemini",name ="gemini-2.5-pro",img_buffer =None ,prompt =None ,clean_text =True ):#line:363
    if model =="gemini":#line:364
        OOOO00OO000000O00 =Gemini (model_name =name )#line:365
        return OOOO00OO000000O00 .send (img_buffer =img_buffer ,prompt =prompt ,clean_text =clean_text )#line:366
    elif model =="github":#line:368
        OO0OOOO0OOO000OO0 =ChatGPT (model_name =name )#line:369
        return OO0OOOO0OOO000OO0 .send (img_buffer =img_buffer .getvalue (),prompt =prompt ,clean_text =clean_text )#line:370
def kill ():#line:372
    global exit_requested #line:373
    logger .info ("Exiting p4b gracefully.")#line:374
    os .system ('cls'if os .name =='nt'else 'clear')#line:375
    mmtrp("c")#line:376
    exit_requested =True #line:377
    if os .name !='nt':#line:378
        os ._exit (0 )#line:379
    else :#line:380
        exit (0 )#line:381
def pa():#line:383
    OOO000OO00OO00O0O =argparse .ArgumentParser (description ="p4b - A vertical within Bruhmastra")#line:384
    OOO000OO00OO00O0O .add_argument ("--silent","-s",action ="store_true",help ="Launch application as a background process")#line:385
    OOO000OO00OO00O0O .add_argument ("--disable-hotkeys",action ="store_true",help ="Disable keyboard hotkeys")#line:386
    OOO000OO00OO00O0O .add_argument ("--no-welcome",action ="store_true",help ="No welcome message on startup")#line:387
    OOO000OO00OO00O0O .add_argument ("--reset-config",action ="store_true",help ="Reset configuration file")#line:388
    return OOO000OO00OO00O0O .parse_args ()#line:389
def main ():#line:392
    OOO000000O0000O00 =pa()#line:393
    global GEMINI_API_KEY ,GITHUB_TOKEN #line:394
    try :#line:395
        if OOO000000O0000O00 .reset_config :#line:396
            sc()#line:397
            return #line:398
        if OOO000000O0000O00 .silent :#line:400
            ss()#line:401
            return #line:402
        if not OOO000000O0000O00 .disable_hotkeys :#line:404
            GEMINI_API_KEY ,GITHUB_TOKEN =check_config ()#line:405
            time .sleep (1 )#line:407
            mmtrp("c",launch =True )#line:408
            if not OOO000000O0000O00 .no_welcome :#line:410
                sw()#line:411
            keyboard .add_hotkey ("alt+shift+1",lambda :pc(model ="gemini",name ="gemini-2.5-flash-lite-preview-06-17"))#line:413
            keyboard .add_hotkey ("alt+shift+2",lambda :pc(model ="gemini",name ="gemini-2.5-flash"))#line:414
            keyboard .add_hotkey ("alt+shift+3",lambda :pc(model ="gemini",name ="gemini-2.5-pro"))#line:415
            keyboard .add_hotkey ("alt+shift+4",lambda :pc(model ="github",name ="openai/gpt-4.1"))#line:416
            keyboard .add_hotkey ("alt+shift+t",tcc)#line:418
            keyboard .add_hotkey ("alt+shift+q",kill )#line:419
        while not exit_requested :#line:421
            time .sleep (0.1 )#line:422
    except KeyboardInterrupt :#line:424
        os .system ('cls'if os .name =='nt'else 'clear')#line:425
    except Exception as O0OOOOO000OOO0000 :#line:426
        logger .exception (f"An error occurred: {str(O0OOOOO000OOO0000)}")#line:427
    finally :#line:428
        keyboard .unhook_all ()#line:429
        if os .name !='nt':#line:430
            os ._exit (0)#line:431
if __name__ =="__main__":#line:433
    main ()