from pathlib import PureWindowsPath

import base64
import datetime
import re
import time

from appium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


from models import *

MIN_NUM_IMAGES = 9
RootPath = PureWindowsPath(r'S:\storage\0')

RunStamp = base64.urlsafe_b64encode(int(time.time()).to_bytes(4,'big')).decode().replace('=','')
RunPath  = RootPath/RunStamp
print(RunStamp, RunPath)

session = Session()

def launchApp(desired_caps):
    # desired_caps["ms:experimental-webdriver"] = True

    # dut_url = "http://win10z:4723"
    dut_url = "http://192.168.11.101:4723"
    driver = webdriver.Remote(
            command_executor = dut_url,
            desired_capabilities = desired_caps)
    return driver

def getDriverFromWin( win):
    win_handle1 = win.get_attribute("NativeWindowHandle")
    win_handle = format(int(win_handle1), 'x') # convert to hex string

    # Launch new session attached to the window
    desired_caps = {}
    desired_caps["appTopLevelWindow"] = win_handle
    driver = launchApp(desired_caps)
    driver.switch_to.window(win_handle)
    return driver

def getDict(row):
    d = {}

    # num_images = row.find_elements_by_name('study.num_images')
    # if not num_images or int(num_images[0] < 9):
    #     return d

    # for e in row.find_elements_by_xpath('//DataItem'):
    for e in row.find_elements_by_tag_name('DataItem'):
        # d[e.get_attribute('Name')] = e.get_attribute('Value.Value')
        name  = e.get_attribute('Name').strip()
        value = e.get_attribute('Value.Value')
        if value:
            value = value.strip()
        d[name] = value
        # if name == 'study.num_images' and int(value)<MIN_NUM_IMAGES:
        #     return d

    return d


# Launch a driver for the Windows Desktop (Root)
desired_caps = {}
desired_caps["app"] = "Root"
desktop = launchApp(desired_caps)


# Input and check (Chinese?)
def edit_input(control, text):
    control.send_keys(text)
    time.sleep(1)
    if control.text != text: # Chinese input method?
        control.send_keys(Keys.LEFT_SHIFT)
        control.send_keys(Keys.BACKSPACE * len(text))
        control.send_keys(text)

        if control.text != text:
            print('Error in edit_input',control,text)
            exit()
            control.send_keys(Keys.ALT, Keys.F4)

def CloseItemPanel():
    for i in range(9):
        OpenItemPanel = desktop.find_elements_by_accessibility_id("OpenItemPanel")
        if not OpenItemPanel:
            break
        print('CloseItemPanel', i)
        ActionChains(desktop).move_to_element(OpenItemPanel[0]).perform()
        button = OpenItemPanel[0].find_element_by_xpath('//Button')
        button.click()

    # exit()


def check_error():
    
    button = desktop.find_elements_by_xpath('*/Window[@Name="錯誤"]/Button[@Name="確定"]')
    if button:
        print (button[0].text)
        button[0].send_keys(Keys.ENTER)
        # view = WebDriverWait(desktop, 20).until(
        #     EC.presence_of_element_located((By.ACCESSIBILITY_ID, "LoginView"))
        # )

    button = desktop.find_elements_by_xpath('*/Window[@Name="發生錯誤"]/Button[@Name="確定"]')
    if button:
        print (button[0].text)
        button[0].send_keys(Keys.ENTER)

        view = WebDriverWait(desktop, 20).until(
            EC.presence_of_element_located((By.ACCESSIBILITY_ID, "LoginView"))
        )

    view = desktop.find_elements_by_accessibility_id('ApplicationView')

    # Close Viewer
    CloseItemPanel()

    # if view:
    #     view[0].send_keys(Keys.ALT, Keys.F4)

    # exit()

# Login if necessary, return ApplicationView

def login():
    ID = '004552'
    password = 'n122119493'

    win = desktop.find_elements_by_accessibility_id('ApplicationView')
    if win:
        win[0].send_keys(Keys.ALT, Keys.F4)
        time.sleep(5)

    # view = desktop.find_element_by_accessibility_id('LoginView')

    # Start app as Administrator
    try:
        view = desktop.find_element_by_accessibility_id('LoginView')
    except:
        desired_caps = {}
        desired_caps["app"] = r"C:\Program Files (x86)\AGFA\IMPAX Client\6.5.2.114\impax-client-main.exe"

        view = launchApp(desired_caps).find_element_by_accessibility_id('LoginView')


    userid = view.find_element_by_accessibility_id('userIDText')
    edit_input(userid, ID)
    # userid.send_keys(ID)
    # if userid.text != ID: # Chinese input method?
    #     userid.send_keys(Keys.LEFT_SHIFT)
    #     userid.send_keys(Keys.BACKSPACE * len(ID))
    #     userid.send_keys(ID)

    view.find_element_by_accessibility_id('passwordText').send_keys(password)
    view.find_element_by_accessibility_id('loginButton').click()

    win = WebDriverWait(desktop, 20).until(
        EC.presence_of_element_located((By.ACCESSIBILITY_ID, "ApplicationView"))
    )
    return win


# win = desktop.find_element_by_name('IMPAX 6.5.2.114 Enterprise Unlimited')
# print(win)
# driver = getDriverFromWin(win)
# print(driver)

check_error() # also kill ApplicationView
win = login()


# try:
#     win = desktop.find_element_by_accessibility_id('ApplicationView')
# except:
#     login()

#     win = WebDriverWait(desktop, 20).until(
#         EC.presence_of_element_located((By.ACCESSIBILITY_ID, "ApplicationView"))
#     )

# print(win)
driver = getDriverFromWin(win)
# driver = win    #AttributeError: 'WebElement' object has no attribute 'w3c' (ActionChains)
print(driver)




def saveSeries(quality, exportPath):


    position = driver.find_element_by_accessibility_id('StudyImageViewer').find_element_by_name("Screen_0_format_5_Position_0_0")

    # ActionChains(driver).context_click(driver.find_element_by_name("Screen_0_format_5_Position_0_0")).perform()
    ActionChains(driver).context_click(position).perform()

    # try:
    #     DisplayMenuForm = desktop.find_element_by_accessibility_id('DisplayMenuForm0')
    # except:
    #     DisplayMenuForm = desktop.find_element_by_accessibility_id('DisplayMenuForm0')

    DisplayMenuForm = WebDriverWait(desktop, 20).until(
        EC.presence_of_element_located((By.ACCESSIBILITY_ID, "DisplayMenuForm0"))
    )

    # time.sleep(1)
    # # desktop.find_elements_by_xpath('*')

    # ActionChains(desktop).send_keys(Keys.ARROW_DOWN).perform()
    # ActionChains(desktop).send_keys(Keys.ARROW_DOWN).perform()

    # DisplayMenuForm = desktop.find_element_by_accessibility_id('DisplayMenuForm0')

    # desktop2 = launchApp(desired_caps)

    # DisplayMenuForm = desktop.find_element_by_accessibility_id('DisplayMenuForm0')
    # DisplayMenuForm = desktop.find_element_by_name('DisplayMenuForm')
    # print(DisplayMenuForm, DisplayMenuForm.tag_name, DisplayMenuForm.text)

    ActionChains(desktop).move_to_element(DisplayMenuForm.find_element_by_name('輸出')).perform()
    ActionChains(desktop).click(DisplayMenuForm.find_element_by_name('影像序列')).perform()

    # export = WebDriverWait(DisplayMenuForm, 20).until(
    #     # EC.presence_of_element_located((By.NAME, "影像序列"))
    #     EC.element_to_be_clickable((By.NAME, "影像序列"))
    # )

    # export.click()

    # DisplayMenuForm.find_element_by_name('影像序列').click()

    view = WebDriverWait(driver, 20).until(
        EC.presence_of_element_located((By.ACCESSIBILITY_ID, "JPEGDlgView"))
    )
    # view = driver.find_element_by_accessibility_id('JPEGDlgView') 

    cb = view.find_element_by_xpath('//ComboBox[2]')
    edit = cb.find_element_by_xpath('//Edit')
    up   = cb.find_element_by_name('Up')
    down = cb.find_element_by_name('Down')
    while int(edit.get_attribute('Value.Value')) < quality:
        up.click()
    while int(edit.get_attribute('Value.Value')) > quality:
        down.click()

    export = view.find_element_by_xpath(r'//Edit[@Name="匯出位置："]')

    while len(export.text):
        export.send_keys(Keys.BACKSPACE)

    export.send_keys(str(exportPath)+'\\')

    # exit()

    driver.find_element_by_accessibility_id('btnOK').click()
    driver.find_element_by_accessibility_id('btnCancel').click()

    # desktop2.close()
    # desktop2.quit()

def screen_1x1():

    # top = WebDriverWait(driver, 600).until(
    #     EC.presence_of_element_located((By.ACCESSIBILITY_ID, "TOP_TOOLBAR0"))
    # )

    box = desktop.find_elements_by_accessibility_id('GenericDialogBox')
    if box:
        box[0].find_element_by_name("確定").click()

    # if driver.find_element_by_accessibility_id('StudyImageViewer').find_elements_by_name("Screen_0_format_5_Position_0_0"):
    #     return
    
    top = driver.find_element_by_accessibility_id("TOP_TOOLBAR0")
    button = top.find_element_by_xpath('//Button[5]')
    ActionChains(driver).click(button).perform()
    AfxWnd90u = driver.find_element_by_xpath(r'//Pane[@ClassName="AfxWnd90u"][1]')
    ActionChains(driver).click(AfxWnd90u).perform()

    return 

    # desktop = launchApp({'app': 'Root'})

    # # position = driver.find_element_by_accessibility_id('StudyImageViewer').find_element_by_name("Screen_0_format_5_Position_0_0")
    # box = desktop.find_elements_by_accessibility_id('GenericDialogBox')
    # if box:
    #     box[0].find_element_by_name("確定").click()


    # for i in range(3):
    #     desktop = launchApp({'app': 'Root'})
    #     win = desktop.find_element_by_accessibility_id('ApplicationView')
    #     d2 = getDriverFromWin(win)

    #     StudyImageViewer = d2.find_elements_by_accessibility_id('StudyImageViewer')

    #     if StudyImageViewer:
    #         position = StudyImageViewer[0].find_elements_by_name("Screen_0_format_5_Position_0_0")
    #         if position:
    #             break

    #     print('screen 1x1', i)

    #     top = d2.find_elements_by_accessibility_id("TOP_TOOLBAR0")
    #     if top:
    #         button = top[0].find_element_by_xpath('//Button[5]')
    #         ActionChains(d2).click(button).perform()
    #         AfxWnd90u = d2.find_element_by_xpath(r'//Pane[@ClassName="AfxWnd90u"][1]')
    #         ActionChains(d2).click(AfxWnd90u).perform()


pattern_series_uid = r'series_uid ] = "([.0-9T]+)"'
prog_series_uid = re.compile(pattern_series_uid)
def getSeriesDocument():

    screen_1x1()
    position = driver.find_element_by_accessibility_id('StudyImageViewer').find_element_by_name("Screen_0_format_5_Position_0_0")

    # position = screen_1x1()

    ActionChains(driver).key_down(Keys.LEFT_CONTROL).context_click(position).key_down(Keys.LEFT_CONTROL).perform()

    ActionChains(desktop).send_keys(Keys.ARROW_DOWN).perform()
    ActionChains(desktop).send_keys(Keys.ARROW_DOWN).perform()

    DisplayMenuForm = desktop.find_element_by_accessibility_id('DisplayMenuForm0')

    ActionChains(desktop).move_to_element(DisplayMenuForm.find_element_by_name('資訊')).perform()
    # ActionChains(desktop).click(DisplayMenuForm.find_element_by_name('服務視窗')).perform()
    DisplayMenuForm.find_element_by_name('服務視窗').click()


    # DisplayMenuForm.find_element_by_accessibility_id('lr_informationStrip').click()
    # DisplayMenuForm.find_element_by_accessibility_id('資訊Strip_SubMenu').click()
    position.click()

    tool = driver.find_element_by_name("Display Service Tool")

    doc = []

    for e in tool.find_elements_by_xpath("//Document"):
        # print(e, e.tag_name, e.text, e.get_attribute('AutomationId'))
        doc.append(e.text)

    result = prog_series_uid.search(doc[1])
    print(result)


# [ series, date_time_modified ] = 1453532533 ( 4, 4 )\r\n  
# [ series, series_number ] = "3" ( 1, 2 )\r\n  
# [ series, manufacturer ] = "GE MEDICAL SYSTEMS" ( 18, 19 )\r\n  
# [ series, series_ref ] = 31044392 ( 8, 8 )\r\n  
# [ series, manufacturer_model_name ] = "Signa HDxt" ( 10, 11 )\r\n  
# [ series, series_time ] = "150149" ( 6, 7 )\r\n  
# [ series, series_uid ] = "1.2.840.113619.2.244.6945.1127238.26918.1453507651.969" ( 54, 55 )\r\n  
# [ series, modality ] = "MR" ( 2, 3 )\r\n  
# [ series, station_name ] = "CGEMR1C1" ( 8, 9 )\r\n  
# [ series, study_ref ] = 29907821 ( 8, 8 )\r\n  
# [ series, series_date ] = "20160123" ( 8, 9 )\r\n  
# [ series, date_time_created ] = 1453532533 ( 4, 4 )\r\n  
# [ series, series_description ] = "Ax T2 FLAIR" ( 11, 12 )

    tool.find_element_by_accessibility_id('Close').click()
    ActionChains(driver).context_click(position).perform()

    return result[1], doc


def getStudyByViewer(accessionNumber, studyPath):

    # ### Get study report last
    # driver.find_element_by_accessibility_id('ShowTextArea').click()
    # # driver.find_element_by_accessibility_id('reportTab').click()
    # report = driver.find_element_by_accessibility_id('reportControl').find_element_by_xpath('//Document').text
    # driver.find_element_by_accessibility_id('_textAreaHideButton').click()
    # print(report)
    # exit()

    # time.sleep(1)    

    # Make it 1x1 view, Try to moved to saveSeries and getSeriesDocument?
    # driver.find_element_by_accessibility_id("TOP_TOOLBAR0").find_element_by_xpath('//Button[5]').click()
    # driver.find_element_by_xpath(r'//Pane[@ClassName="AfxWnd90u"][1]').click()


    # top = WebDriverWait(driver, 20).until(
    #     EC.presence_of_element_located((By.ACCESSIBILITY_ID, "TOP_TOOLBAR0"))
    # )

    screen_1x1()

    # top = win.find_element_by_accessibility_id("TOP_TOOLBAR0")
    # button = top.find_element_by_xpath('//Button[5]')
    # button.click()
    # AfxWnd90u = win.find_element_by_xpath(r'//Pane[@ClassName="AfxWnd90u"][1]')
    # AfxWnd90u.click()

    # driver = getDriverFromWin(win)

    items = driver.find_elements_by_xpath(r'//ListItem[@AutomationId="ListViewItem-0"]/../ListItem')
    if len(items) == 0:
        toolbar = driver.find_element_by_accessibility_id("STANDARD_TOOLBAR0")
        toolbar.find_element_by_xpath('//Button[1]').click()
        items = driver.find_elements_by_xpath(r'//ListItem[@AutomationId="ListViewItem-0"]/../ListItem')

    num_images = 0

    for c in driver.find_elements_by_xpath(r'//ListItem[@AutomationId="ListViewItem-0"]/../ListItem'):

        # AutomationId = 
        print(c.get_attribute('AutomationId'), c.tag_name, c.text)
        ActionChains(driver).double_click(c).perform()

        name = c.text
        num_images += int(name.split(' : ')[1])
        uid, doc = getSeriesDocument()
        # print(doc)
        # print(uid)
        s = session.query(Series).get(uid)
        if s is None:
            s = Series(series_uid = uid)
            session.add(s)
        s.name      = name
        s.document0 = doc[0]
        s.document1 = doc[1]

        s.accession_number = accessionNumber

        # p.saved = datetime.datetime.now()
        session.commit()



        # Save Demographics shown
        saveSeries(100, studyPath / 'shown' / s.slugify())
        driver.find_element_by_accessibility_id("TOP_TOOLBAR0").find_element_by_xpath('//Button[1]').click()
        # Save Demographics hidden
        saveSeries(100, studyPath / 'hidden' / s.slugify())
        driver.find_element_by_accessibility_id("TOP_TOOLBAR0").find_element_by_xpath('//Button[1]').click()


    ### Get study report last
    driver.find_element_by_accessibility_id('ShowTextArea').click()
    try:
        report = driver.find_element_by_accessibility_id('reportControl').find_element_by_xpath('//Document').text
    except:
        report = None

    driver.find_element_by_accessibility_id('_textAreaHideButton').click()

    s = session.query(Study).get(accessionNumber)
    if s is None:
        s = Study(accession_number = accessionNumber)
        session.add(s)
    s.report = report

    if s.num_images == num_images and (report or (datetime.date.today()-s.study_date).days>99):
        s.success = True

    s.run = RunStamp
    session.commit()


def getStudyByGrid(study, patientPath):

    # print(patientPath)
    # exit()

    # print(driver.find_element_by_accessibility_id("TOP_TOOLBAR0"))


    driver.find_element_by_accessibility_id("resetButton").click()
    # driver.find_element_by_accessibility_id("accessionNumberText").find_element_by_xpath(r'//Edit[@Name="檢查流水號"]').send_keys(accessionNumber)

    accession = win.find_element_by_accessibility_id('accessionNumberText').find_element_by_tag_name('Edit')
    edit_input(accession, study.accession_number.replace('@', ''))
    # accession.send_keys(study.accession_number)
    # time.sleep(1)
    # if accession.text != study.accession_number: # Chinese input method?
    #     accession.send_keys(Keys.LEFT_SHIFT)
    #     accession.send_keys(Keys.BACKSPACE * len(study.accession_number))
    #     accession.send_keys(study.accession_number)

    driver.find_element_by_accessibility_id("searchButton").click()
    grid = driver.find_element_by_accessibility_id("grid")

    # print(1)
    # for i, e in enumerate(grid.find_elements_by_xpath('*')):
    #     print(e, e.tag_name, e.text)
    # exit()
    # print(2)

    for i, e in enumerate(grid.find_elements_by_xpath('//DataItem[@Name="View"]/..')):


        print(i, e.tag_name)
        d = getDict(e)
        print(d)

        if 'study.num_images' not in d or int(d['study.num_images']) < MIN_NUM_IMAGES:
            continue

        # 取回 nearline, But dont wait
        if d['View'] == 'nearline':
            ActionChains(driver).context_click(e.find_element_by_name('View')).perform()
            # desktop.find_element_by_xpath(r'Pane/Menu[@Name="路徑位置"]/MenuItem[@Name="取回"]').click()
            desktop.find_element_by_name('路徑位置').find_element_by_name("取回").click() # faster 

            print('skip nearline',study.accession_number)

            return  


        ActionChains(driver).double_click(e.find_element_by_name('View')).perform()

        # print(study.naming())
        # exit()
        # getStudyByViewer(study.accession_number, patientPath/(datetime.datetime.strptime(d['study.study_date'], '%Y/%m/%d').strftime('%Y-%m-%d-')+accessionNumber))
        getStudyByViewer(study.accession_number, patientPath/study.naming())

        #close image viewer
        CloseItemPanel()
    

        # exit()

        # "/Pane[@ClassName=\"#32769\"][@Name=\"桌面 1\"]/Window[@Name=\"IMPAX 6.5.2.114 Enterprise Unlimited\"][@AutomationId=\"ApplicationView\"]/Pane[@AutomationId=\"displayPanel\"]/Pane[@AutomationId=\"DisplayView\"]/Pane[@Name=\"TOP_TOOLBAR0\"][starts-with(@AutomationId,\"TOP_TOOLBAR\")]/Button[starts-with(@ClassName,\"WindowsForms10\")]";


def getPatient(ID, rescanStudy = True):


    if rescanStudy:


        driver.find_element_by_accessibility_id("resetButton").click()

        # patientId = win.find_element_by_accessibility_id('patientIdText').find_element_by_xpath(r'//Edit[@Name="病歷號碼"]')
        # patientId = win.find_element_by_accessibility_id('patientIdText').find_element_by_tag_name('Edit')
        patientId = driver.find_element_by_accessibility_id('patientIdText').find_element_by_tag_name('Edit')
        edit_input(patientId, ID)
        # patientId.send_keys(ID)
        # time.sleep(1)
        # if patientId.text != ID: # Chinese input method?
        #     patientId.send_keys(Keys.LEFT_SHIFT)
        #     patientId.send_keys(Keys.BACKSPACE * len(ID))
        #     patientId.send_keys(ID)

        # driver.find_element_by_accessibility_id("patientIdText").find_element_by_xpath(r'//Edit[@Name="病歷號碼"]').send_keys(patientId)
        driver.find_element_by_accessibility_id("searchButton").click()
        grid = driver.find_element_by_accessibility_id("grid")

        try:
            DownButton = grid.find_element_by_accessibility_id("DownButton")
        except:
            DownButton = None

        print(1)

        # for i, e in enumerate(grid.find_elements_by_xpath('*/*')):
        # for i, e in enumerate(grid.find_elements_by_xpath('//DataItem[@Name="View"]/..')):
        for i, e in enumerate(grid.find_elements_by_xpath('*/Custom')):
            print(i, e.tag_name, e.text)

            if not e.text.isdigit():
                continue

            d = getDict(e)
            print(d)
            if ('study.accession_number' not in d) or not d['study.accession_number']:
                continue

            p = session.query(Patient).get(d['patient.patient_id'])
            if p is None:
                p = Patient(patient_id = d['patient.patient_id'])
                session.add(p)
            p.patient_name         = d['patient.patient_name']
            p.patient_name_ph_utf8 = d['patient.patient_name_ph_utf8']

            # p.saved = datetime.datetime.now()
            session.commit()

            s = session.query(Study).get(d['study.accession_number'])
            if s is None:
                s = Study(accession_number = d['study.accession_number'])
                session.add(s)
            # else:
            #     #skip study already success
            #     if s.success:
            #         continue
            s.date_time_created = d['study.date_time_created']
            s.modality          = d['study.modality']
            s.num_images        = d['study.num_images']
            s.status            = d['study.status']
            s.study_date        = datetime.datetime.strptime(d['study.study_date'], '%Y/%m/%d')
            s.study_description = d['study.study_description']
            s.study_time        = d['study.study_time']

            s.patient_id        = d['patient.patient_id']

            # p.saved = datetime.datetime.now()
            session.commit()

            # if int(d['study.num_images']) < MIN_NUM_IMAGES:
            #     continue

            # if 'View'in d and d['View']==None:
            #     driver.find_element_by_accessibility_id("DownButton").click()
            #     exit()

            # continue


            if (not s.success) and s.num_images > MIN_NUM_IMAGES:

                # if  d['View'] not in ['Available', 'VIEWABLE', 'VIEWING']:
                if d['View'] == 'nearline':
                    ActionChains(driver).context_click(e.find_element_by_name('View')).perform()
                    # desktop.find_element_by_xpath(r'Pane/Menu[@Name="路徑位置"]/MenuItem[@Name="取回"]').click()
                    desktop.find_element_by_name('路徑位置').find_element_by_name("取回").click() # faster   
                    # getDriverFromWin(desktop.find_element_by_name('路徑位置')).find_element_by_name("取回").click()   

                    # print(desktop.find_element_by_xpath(r'Pane/Menu[@Name="路徑位置"]/MenuItem[@Name="取回"]'))
                    # exit()
            if DownButton:
                DownButton.click()

        if DownButton:
            UpPageButton = grid.find_element_by_accessibility_id("UpPageButton")
            try:
                while True:
                    UpPageButton.click()
            except:
                pass
        
        if p.counter is None:
            p.counter = 1
        else:
            p.counter += 1
        session.commit()

    for study in session.query(Patient).get(ID).studies:
        if study.success or study.num_images < MIN_NUM_IMAGES:
            continue
        getStudyByGrid(study, RunPath/ID)



if __name__ == '__main__':

    rescan = True

    getPatient('3009684', rescanStudy=rescan)
    # getPatient('2347157', rescanStudy=rescan)

    # getStudyByViewer('T0159343504', r'S:\storage\0')
    # getStudyByGrid('T0159343504', r'S:\storage\0')
