'''Content getters'''
import os
import re
import shutil
from datetime import date, datetime, timedelta
from time import sleep
import json

import imageio
import requests
import yaml
from bs4 import BeautifulSoup
from PIL import Image
from retrying import retry
from telegram import InlineKeyboardButton

from config.timeouts import ASTRO, EARTHQUAKE, ECLIPSE, TIDE, TYPHOON, WARN
from helpers import decorators
from selenium import webdriver


def cleanhtml(raw_html):
    cleanr = re.compile('<.*?>')
    cleantext = re.sub(cleanr, '', raw_html)
    return cleantext


class Source(object):
    @classmethod
    def __latestImgs(cls):
        '''rdar images: 64, 128, 256'''
        source = 'http://www.hko.gov.hk/wxinfo/radars/radar64n.htm'
        txt = requests.get(source).text
        soup = BeautifulSoup(txt, 'html.parser')

        result = ''

        for tag in soup.find_all('script'):
            if 'picture[0][0]' in str(tag.string):
                result = tag.string

        radar_lists = {
            '64': list(),
            '128': list(),
            '256': list()
        }

        for line in result.split("\n"):
            if '.jpg' in line:
                if 'rad_256' in line:
                    radar_lists['256'].append(line)
                elif 'rad_128' in line:
                    radar_lists['128'].append(line)
                elif 'rad_064' in line:
                    radar_lists['64'].append(line)

        result = {
            '64': radar_lists['64'][-1].split("=\"")[-1].split("\";")[0],
            '128': radar_lists['128'][-1].split("=\"")[-1].split("\";")[0],
            '256': radar_lists['256'][-1].split("=\"")[-1].split("\";")[0]
        }
        return result

    @classmethod
    def getUptime(cls):
        start_time = yaml.safe_load(
            open("assets/thread_stats.yml"))["scanner_started"]
        td = datetime.now() - start_time

        days, seconds = td.days, td.seconds
        hours = (days * 24 + seconds // 3600) % 24
        minutes = (seconds % 3600) // 60
        seconds = seconds % 60

        uptime = {
            "days": days,
            "hours": hours,
            "minutes": minutes,
            "seconds": seconds,
            "s_padding": "",
            "start_time": start_time
        }
        if uptime["days"] > 1:
            uptime["s_padding"] = "s"

        return uptime

    @classmethod
    def getWeatherChart(cls):
        base = 'http://www.hko.gov.hk/wxinfo/currwx/'
        src = base + 'wxcht.htm'
        driver = webdriver.PhantomJS()
        driver.get(src)
        target = driver.page_source
        driver.quit()
        soup = BeautifulSoup(target, 'html.parser')
        img = soup.find("img", {"id": "weatherChart"})

        url = (base + str(img['src']).split("/wxinfo/currwx/")[-1])
        cls.__getUrlImg(url, 'images/chart.gif')

    @classmethod
    def getNowData(cls):
        src = "http://www.weather.gov.hk/wxinfo/json/one_json.xml"

        # get json data
        r = requests.get(src)
        r.encoding = "utf-8"
        json_data = json.loads(r.text)

        hko = json_data["hko"]
        r_data = "Updated at {}\n⬇{} - ⬆{}\n🌡 {}\n💦 {}"

        return r_data.format(
            hko["BulletinTime"][-4:],
            hko["HomeMinTemperature"], hko["HomeMaxTemperature"],
            hko["Temperature"],
            hko["RH"])

    @classmethod
    @decorators.MWT(timeout=60 * 15)
    def get_special_tips(cls, *, lang="en"):
        """
        :lang(en/zh): - ``str`` language used for the retrieved tips
        """
        base = "http://www.hko.gov.hk/textonly/v2/warning/{}"
        src_file = ""
        if lang == 'en':
            src_file = base.format("sweather_tips.htm")
        elif lang == 'zh':
            src_file = base.format("sweather_tips_uc.htm")

        request = requests.get(src_file)
        request.encoding = "utf-8"
        soup = BeautifulSoup(request.text, 'html.parser')

        results = []

        escapes = ["\r", "\n"]

        target_list = soup.find_all("li")
        if len(target_list) is 0:
            for element in soup.find_all("ul"):
                data = cleanhtml(str(element))
                for escape in escapes:
                    data = data.replace(escape, "")
                results.append(data)

        else:
            for element in soup.find_all("li"):
                e_str = cleanhtml(str(element))
                pad_pos = e_str.find("Issued")
                if lang == 'en':
                    e_str = e_str[:pad_pos] + " " + e_str[pad_pos:]
                results.append(e_str)

        return "".join(results)

    @classmethod
    @decorators.MWT(timeout=EARTHQUAKE)
    def getEarthQuakeData(cls):
        src = 'http://www.weather.gov.hk/gts/equake/quake-info.htm'
        driver = webdriver.PhantomJS()
        driver.get(src)
        driver.find_element_by_id("km1000").click()
        sleep(5)
        source = driver.page_source
        driver.quit()

        soup = BeautifulSoup(source, 'html.parser')

        mag = soup.find_all("td", {"class": "td_mag", "style": ""})
        region = soup.find_all("td", {"class": "td_region", "style": ""})

        mags = []
        regions = []

        for i in mag:
            mags.append(str(i.string))
        del mags[-1]

        for i in region:
            regions.append(str(i)
                           .split("\">")[-1]
                           .split("</a")[0]
                           .replace("</span><br/>", " "))
        del regions[-1]

        return {
            "mags": mags,
            "regions": regions
        }

    @classmethod
    @decorators.MWT(timeout=TIDE)
    def getTideData(cls):
        driver = webdriver.PhantomJS()
        driver.get("http://www.hko.gov.hk/m/home.htm")
        soup = BeautifulSoup(driver.page_source, 'html.parser')
        driver.quit()
        result = soup.find("div", {"id": "tide_content"})
        result2 = BeautifulSoup(str(result), 'html.parser')
        result = []

        for i in result2.find_all("td"):
            if i.string is not None:
                if ':' in i.string:
                    result.append(i.string + "\n")
                else:
                    result.append(i.string + " ")

        return "". join(result)

    @classmethod
    @decorators.MWT(timeout=ASTRO)
    def getAstroData(cls):
        driver = webdriver.PhantomJS()
        driver.get("http://www.hko.gov.hk/m/home.htm")
        soup = BeautifulSoup(driver.page_source, 'html.parser')
        driver.quit()

        astro = {
            'sunset': soup.find(
                "div", {"id": "astro"}).find(
                "td", {"id": "sunSet"}).string,
            'sunrise': soup.find(
                "div", {"id": "astro"}).find(
                "td", {"id": "sunRise"}).string,
            'moonset': soup.find(
                "div", {"id": "astro"}).find(
                "td", {"id": "moonSet"}).string,
            'moonrise': soup.find(
                "div", {"id": "astro"}).find(
                "td", {"id": "moonRise"}).string,
            'sun': "today ",
            'moon': "today "
        }

        if '-' in astro['moonset'] or '-' in astro['moonrise']:
            astro['moon'] = "today "
        else:
            sunset = int(astro['sunset'].split(":")[0])
            sunrise = int(astro['sunrise'].split(":")[0])
            moonset = int(astro['moonset'].split(":")[0])
            moonrise = int(astro['moonrise'].split(":")[0])

            if sunset < sunrise:
                astro["sun"] = "tomorrow "
            if moonset < moonrise:
                astro["moon"] = "tomorrow "

        return astro

    def get_radar_images(self, img_scale="64"):
        '''to be used to create gif'''
        base_s = 'http://www.hko.gov.hk/wxinfo/radars/'
        result_data = self.__latestImgs()

        img_file = "images/{}_img/{}.jpg".format(
            img_scale, "{:%H_%M}".format(datetime.now()))

        self.__getUrlImg(base_s + result_data[img_scale], img_file)

        # compress saved radar jpegs
        Image.open(img_file).save(img_file, quality=60)

    @classmethod
    def generate_radar_gif(cls, scale=64, length=120):
        '''
        creates a gif based on scale
        and duration(in minutes) selected
        '''
        dir_name = "images/{}_img/".format(scale)
        images = os.listdir(dir_name)
        timestamps, images_list, frames = [], [], []

        # creates a time range in terms of hour_minute
        for minute in range(0, 120):
            timestamps.append(
                "{:%H_%M}.jpg".format(
                    datetime.now() - timedelta(minutes=minute)))

        for img in images:
            if img in timestamps:
                images_list.append("{}{}".format(
                    dir_name, img))

        # creates gif from selected image files
        for filename in images_list:
            frames.append(imageio.imread(filename))
        imageio.mimsave('images/{}_gif.gif'.format(scale),
                        frames, duration=0.5)

    @retry(wait_random_min=1000 * 60 * 3, wait_random_max=1000 * 60 * 5)
    def getLatestRadarImgs(self):
        base_s = 'http://www.hko.gov.hk/wxinfo/radars/'
        result_data = self.__latestImgs()

        for result in result_data:
            sleep(5)
            self.__getUrlImg(
                base_s + result_data[result],
                'images/' + result + '.jpg')

        Image.open('images/128.jpg').save('images/128_c.jpg', quality=60)
        Image.open('images/256.jpg').save('images/256_c.jpg', quality=60)

    @classmethod
    def __getUrlImg(cls, link, dest):
        base = link
        r = requests.get(base, stream=True)
        with open(dest, mode='wb') as file:
            shutil.copyfileobj(r.raw, file)
        del r

    @classmethod
    def __monthToNum(cls, month_name):
        return {
            'January': 1,
            'February': 2,
            'March': 3,
            'April': 4,
            'May': 5,
            'June': 6,
            'July': 7,
            'August': 8,
            'September': 9,
            'October': 10,
            'November': 11,
            'December': 12
        }[month_name]

    @decorators.MWT(timeout=ECLIPSE)
    def getNextEclipse(self, type_=str()):
        src = 'http://www.hko.gov.hk/gts/event/event-solar-eclps14_e.htm'

        if type_ == 'lunar':
            src = 'http://www.hko.gov.hk/gts/event/event-lunar-eclps14_e.htm'

        soup = BeautifulSoup(requests.get(src).text, 'html.parser')
        res = []
        pos = 7

        for i in soup.find_all("tbody"):
            res.append(i)

        if type_ is 'lunar':
            pos = 6

        e = str(res).split("\n")[pos].split(">")[1].split("<")[0].split(" ")
        e_year = e[2]
        e_month = e[1]
        e_day = e[0]
        now = date.today()
        event = date(int(e_year), self.__monthToNum(e_month), int(e_day))
        diff = event - now

        return {
            'date': str(res).split("\n")[pos].split(">")[1].split("<")[0],
            'type': str(res).split("\n")[-3].split(">")[1].split("<")[0],
            'delta': diff.days
        }

    @classmethod
    @decorators.MWT(timeout=WARN)
    def getWarnings(cls):
        src = 'http://www.hko.gov.hk/textonly/v2/warning/warn.htm'
        txt = requests.get(src).text
        soup = BeautifulSoup(txt, 'html.parser')
        result = []

        for i in soup.find_all('p'):
            if 'HKT' in str(i.string):
                result.append(i.string)
                result.append("\n")

        return "".join(result)

    def getUvIndexImg(self):
        self.__getUrlImg('http://www.hko.gov.hk/wxinfo/uvindex/today.png',
                         'images/uv.png')

    def getTempImg(self):
        self.__getUrlImg('http://www.hko.gov.hk/wxinfo/ts/temp/tempchk.png',
                         'images/temp.png')

    def getWindImg(self):
        self.__getUrlImg('http://www.hko.gov.hk/wxinfo/ts/windchk.png',
                         'images/windavg.png')
        self.__getUrlImg(
            'http://www.hko.gov.hk/wxinfo/ts/windgust/gustchk.png',
            'images/windmax.png')

    @classmethod
    @decorators.MWT(timeout=TYPHOON)
    def getUpdatedTyphoon(cls):
        base = 'http://www.hko.gov.hk/wxinfo/currwx/tc_fixarea_e.htm'
        soup = BeautifulSoup(requests.get(base).text, 'html.parser')
        result = str(soup.find(
            "h1")).split("\">")[-1].split("</")[0].replace(" \r\n<br/>", "")
        return result

    @decorators.MWT(timeout=TYPHOON)
    def getTyphoonImgs(self):
        base = 'http://www.hko.gov.hk/wxinfo/currwx/'
        src = base + 'tc_fixarea_e.htm'
        soup = BeautifulSoup(requests.get(src).text, 'html.parser')
        data = {}
        avail = [[]]

        for i in soup.find_all("img"):
            if 'Tropical' in i['alt']:
                if 'nwp' in i['src']:
                    data['1x'] = base + i['src']
                    avail[0].append(
                        InlineKeyboardButton("1x", callback_data="1x|typhoon"))
                    self.__getUrlImg(data['1x'], 'images/typhoon1x.png')
                elif 'tc' in i['src']:
                    data['2x'] = base + i['src']
                    avail[0].append(
                        InlineKeyboardButton("2x", callback_data="2x|typhoon"))
                    self.__getUrlImg(data['2x'], 'images/typhoon2x.png')
                elif 'zoom' in i['src']:
                    data['3x'] = base + i['src']
                    avail[0].append(
                        InlineKeyboardButton("3x", callback_data="3x|typhoon"))
                    self.__getUrlImg(data['3x'], 'images/typhoon3x.png')

        return avail
