import logging
import os
import time

import requests
from lxml import etree
import urllib.parse
import json
import schedule
from colorama import Fore,init


def getICBCNews()->tuple:
    logging.debug('Getting icbc news...')

    url = 'https://www.icbc.com.cn/ICBC/纪念币专区/default.htm'
    re = requests.get(url)
    html = etree.HTML(re.content.decode('utf8'))
    logging.info(f'Response status is {re.status_code}')

    news = html.xpath('//span[@class="ChannelSummaryList-insty"]/a/@data-collecting-param')
    urls = html.xpath('//span[@class="ChannelSummaryList-insty"]/a/@href')

    newUrl = 'https://www.icbc.com.cn'
    newNews = news[0]
    newUrl += urllib.parse.unquote(urls[0])
    logging.info(f'Got latest news 《{colored(newNews[:8])}...》')

    return newNews, newUrl


def getPBCNews()->tuple:
    logging.debug('Getting pbc news...')

    url = 'http://www.pbc.gov.cn/huobijinyinju/147948/147964/index.html'
    re = requests.post(url)
    html = etree.HTML(re.content.decode('utf8'))
    logging.info(f'Response status is {re.status_code}')

    news = html.xpath('//font[@class="newslist_style"]/a/@title')
    urls = html.xpath('//font[@class="newslist_style"]/a/@href')

    newNews = news[0]
    newUrl = 'http://www.pbc.gov.cn'
    newUrl += urls[0]
    logging.info(f'Got latest news 《{colored(newNews[:8])}...》')

    return newNews, newUrl

def colored(string:str)->str:
    return Fore.RED + string +Fore.RESET

def main(msgChannel:list)->None:

    icbcNews, icbcUrl = getICBCNews()
    pbcNews, pbcUrl = getPBCNews()

    if not os.path.isfile('commemorativeCoins.json'):
        open('commemorativeCoins.json', 'w').close()
        logging.info('Did not find json log, created one.')

    with open('commemorativeCoins.json', 'r') as f:
        oldVersion = json.load(f)
    logging.debug('Read json log.')

    newVersion = oldVersion.copy()
    newVersion['icbc']['news'] = icbcNews
    newVersion['icbc']['url'] = icbcUrl
    newVersion['pbc']['news'] = pbcNews
    newVersion['pbc']['url'] = pbcUrl

    if oldVersion != newVersion:
        # send change
        content = [icbcNews, pbcNews]
        url = [icbcUrl, pbcUrl]
        logging.info(f'Found new article {colored(content)}')

        for sendMsg in msgChannel:
            sendMsg('纪念币更新', content, url)

        with open('commemorativeCoins.json', 'w') as f:
            json.dump(newVersion, f, ensure_ascii=False)

        logging.info('Wrote to json log.')

    else:
        # send heartbeat
        for sendMsg in msgChannel:
            sendMsg('Heartbeat', ['plan is running, did not find new article'], ['a'])
        logging.info(f'did not find new article')



def sendMail(title:str, contents:list, urls:list)->None:
    import yagmail

    content = ''
    
    for url, con in zip(urls, contents):
        content += f'<a href="{url}">{con}</a>'
    yag = yagmail.SMTP('<EMAIL>', 'sfrjjkcpkhhsbefa', host='smtp.qq.com')
    yag.send(to='<EMAIL>', subject=title, contents=content)
    logging.info(f'sent mail {title}')


def showToast(title:str, content:list, *args)->None:
    from win10toast import ToastNotifier

    toast = ToastNotifier()
    for c in content:
        toast.show_toast(title, c)
    logging.info(f'Made toast {title}')

def showNoti(title:str,content:list,urls:list)->None:
    for c,u in zip(content,urls):
        cmd=f'termux-notification --action "termux-open-url {u}" --content "tap to open {title}" --title {content}'
        os.system(cmd)
    logging.info(f'Sent notification {title}')

def getEnv()->list:

    # 1: win 10 toast 2:email 3:android notification
    # todo multi way
    NOTIFIER_CHANNEL=os.getenv('NOTIFIER_CHANNEL','23')
    logging.debug(f'Get system variant NOTIFIER_CHANNEL:{NOTIFIER_CHANNEL}')
    NOTIFIER_CHANNEL=set(NOTIFIER_CHANNEL)

    baseChannel=set('123')

    if not NOTIFIER_CHANNEL.issubset(baseChannel):
        NOTIFIER_CHANNEL &= baseChannel
        logging.warning(colored(f'Only "1" "2" or "3" expected in NOTIFIER_CHANNEL, {NOTIFIER_CHANNEL} was given. Aborted illegal options.'))

    msgChannelDict={
            '1':showToast,
            '2':sendMail,
            '3':showNoti
            }

    msgChannel=[]
    
    for i in NOTIFIER_CHANNEL:
        msgChannel.append(msgChannelDict[i])

    logging.info(f'Message sendMsg set as {NOTIFIER_CHANNEL}:{[f.__name__ for f in msgChannel]}')
    return msgChannel

def logPlan():

    plan = [repr(p) for p in schedule.get_jobs('mainPlan')]
    logging.info('\n'.join(plan))

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s: <%(funcName)s> - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    logging.debug('Started process.')
    #colorama init
    #init(autoreset=True)
    msgChannel=getEnv()

    schedule.every(2).hours.do(logPlan)
    schedule.every().day.at('10:00').do(main,msgChannel=msgChannel).tag('mainPlan')
    
    schedule.run_all()
    while True:
        schedule.run_pending()
        time.sleep(10)

import logging
import os
import time

import requests
from lxml import etree
import urllib.parse
import json
import schedule
from colorama import Fore,init


def getICBCNews()->tuple:
    logging.debug('Getting icbc news...')

    url = 'https://www.icbc.com.cn/ICBC/纪念币专区/default.htm'
    re = requests.get(url)
    html = etree.HTML(re.content.decode('utf8'))
    logging.info(f'Response status is {re.status_code}')

    news = html.xpath('//span[@class="ChannelSummaryList-insty"]/a/@data-collecting-param')
    urls = html.xpath('//span[@class="ChannelSummaryList-insty"]/a/@href')

    newUrl = 'https://www.icbc.com.cn'
    newNews = news[0]
    newUrl += urllib.parse.unquote(urls[0])
    logging.info(f'Got latest news 《{colored(newNews[:8])}...》')

    return newNews, newUrl


def getPBCNews()->tuple:
    logging.debug('Getting pbc news...')

    url = 'http://www.pbc.gov.cn/huobijinyinju/147948/147964/index.html'
    re = requests.post(url)
    html = etree.HTML(re.content.decode('utf8'))
    logging.info(f'Response status is {re.status_code}')

    news = html.xpath('//font[@class="newslist_style"]/a/@title')
    urls = html.xpath('//font[@class="newslist_style"]/a/@href')

    newNews = news[0]
    newUrl = 'http://www.pbc.gov.cn'
    newUrl += urls[0]
    logging.info(f'Got latest news 《{colored(newNews[:8])}...》')

    return newNews, newUrl

def colored(string:str)->str:
    return Fore.RED + string +Fore.RESET

def main(msgChannel:list)->None:

    icbcNews, icbcUrl = getICBCNews()
    pbcNews, pbcUrl = getPBCNews()

    if not os.path.isfile('commemorativeCoins.json'):
        open('commemorativeCoins.json', 'w').close()
        logging.info('Did not find json log, created one.')

    with open('commemorativeCoins.json', 'r') as f:
        oldVersion = json.load(f)
    logging.debug('Read json log.')

    newVersion = oldVersion.copy()
    newVersion['icbc']['news'] = icbcNews
    newVersion['icbc']['url'] = icbcUrl
    newVersion['pbc']['news'] = pbcNews
    newVersion['pbc']['url'] = pbcUrl

    if oldVersion != newVersion:
        # send change
        content = [icbcNews, pbcNews]
        url = [icbcUrl, pbcUrl]
        logging.info(f'Found new article {colored(content)}')

        for sendMsg in msgChannel:
            sendMsg('纪念币更新', content, url)

        with open('commemorativeCoins.json', 'w') as f:
            json.dump(newVersion, f, ensure_ascii=False)

        logging.info('Wrote to json log.')

    else:
        # send heartbeat
        for sendMsg in msgChannel:
            sendMsg('Heartbeat', ['plan is running, did not find new article'], ['a'])
        logging.info(f'did not find new article')



def sendMail(title:str, contents:list, urls:list)->None:
    import yagmail

    content = ''
    
    for url, con in zip(urls, contents):
        content += f'<a href="{url}">{con}</a>'
    yag = yagmail.SMTP('<EMAIL>', 'sfrjjkcpkhhsbefa', host='smtp.qq.com')
    yag.send(to='<EMAIL>', subject=title, contents=content)
    logging.info(f'sent mail {title}')


def showToast(title:str, content:list, *args)->None:
    from win10toast import ToastNotifier

    toast = ToastNotifier()
    for c in content:
        toast.show_toast(title, c)
    logging.info(f'Made toast {title}')

def showNoti(title:str,content:list,urls:list)->None:
    for c,u in zip(content,urls):
        cmd=f'termux-notification --action "termux-open-url {u}" --content "tap to open {title}" --title {content}'
        os.system(cmd)
    logging.info(f'Sent notification {title}')

def getEnv()->list:

    # 1: win 10 toast 2:email 3:android notification
    # todo multi way
    NOTIFIER_CHANNEL=os.getenv('NOTIFIER_CHANNEL','23')
    logging.debug(f'Get system variant NOTIFIER_CHANNEL:{NOTIFIER_CHANNEL}')
    NOTIFIER_CHANNEL=set(NOTIFIER_CHANNEL)

    baseChannel=set('123')

    if not NOTIFIER_CHANNEL.issubset(baseChannel):
        NOTIFIER_CHANNEL &= baseChannel
        logging.warning(colored(f'Only "1" "2" or "3" expected in NOTIFIER_CHANNEL, {NOTIFIER_CHANNEL} was given. Aborted illegal options.'))

    msgChannelDict={
            '1':showToast,
            '2':sendMail,
            '3':showNoti
            }

    msgChannel=[]
    
    for i in NOTIFIER_CHANNEL:
        msgChannel.append(msgChannelDict[i])

    logging.info(f'Message sendMsg set as {NOTIFIER_CHANNEL}:{[f.__name__ for f in msgChannel]}')
    return msgChannel

def logPlan():

    plan = [repr(p) for p in schedule.get_jobs('mainPlan')]
    logging.info('\n'.join(plan))

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s: <%(funcName)s> - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    logging.debug('Started process.')
    #colorama init
    #init(autoreset=True)
    msgChannel=getEnv()

    schedule.every(2).hours.do(logPlan)
    schedule.every().day.at('10:00').do(main,msgChannel=msgChannel).tag('mainPlan')
    
    schedule.run_all()
    while True:
        schedule.run_pending()
        time.sleep(10)

# send change # send heartbeat # 1: win 10 toast 2:email 3:android notification # todo multi way #colorama init #init(autoreset=True)