# -*- coding: utf-8 -*-

import datetime
import json
import time
import requests
import twstock
import sys

from twstock.proxy import get_proxies

SESSION_URL = "http://mis.twse.com.tw/stock/index.jsp"
STOCKINFO_URL = (
    "http://mis.twse.com.tw/stock/api/getStockInfo.jsp?ex_ch={stock_id}&_={time}"
)

# Mock data
mock = False


def _format_stock_info(data) -> dict:
    result = {"timestamp": 0.0, "info": {}, "realtime": {}}

    # Timestamp
    result["timestamp"] = int(data["tlong"]) / 1000

    # Information
    result["info"]["code"] = data["c"]
    result["info"]["channel"] = data["ch"]
    result["info"]["name"] = data["n"]
    result["info"]["fullname"] = data["nf"]
    result["info"]["time"] = datetime.datetime.fromtimestamp(
        int(data["tlong"]) / 1000
    ).strftime("%Y-%m-%d %H:%M:%S")

    # Process best result
    def _split_best(d):
        if d:
            return d.strip("_").split("_")
        return d

    # Realtime information
    result["realtime"]["latest_trade_price"] = data.get("z", None)
    result["realtime"]["trade_volume"] = data.get("tv", None)
    result["realtime"]["accumulate_trade_volume"] = data.get("v", None)
    result["realtime"]["best_bid_price"] = _split_best(data.get("b", None))
    result["realtime"]["best_bid_volume"] = _split_best(data.get("g", None))
    result["realtime"]["best_ask_price"] = _split_best(data.get("a", None))
    result["realtime"]["best_ask_volume"] = _split_best(data.get("f", None))
    result["realtime"]["open"] = data.get("o", None)
    result["realtime"]["high"] = data.get("h", None)
    result["realtime"]["low"] = data.get("l", None)

    # Success fetching
    result["success"] = True

    return result


def _join_stock_id(stocks) -> str:
    if isinstance(stocks, list):
        return "|".join(
            [
                "{}_{}.tw".format("tse" if s in twstock.twse else "otc", s)
                for s in stocks
            ]
        )
    return "{}_{stock_id}.tw".format(
        "tse" if stocks in twstock.twse else "otc", stock_id=stocks
    )


def get_raw(stocks) -> dict:
    req = requests.Session()
    req.get(SESSION_URL, proxies=get_proxies())

    r = req.get(
        STOCKINFO_URL.format(
            stock_id=_join_stock_id(stocks), time=int(time.time()) * 1000
        )
    )

    if sys.version_info < (3, 5):
        try:
            return r.json()
        except ValueError:
            return {"rtmessage": "json decode error", "rtcode": "5000"}
    else:
        try:
            return r.json()
        except json.decoder.JSONDecodeError:
            return {"rtmessage": "json decode error", "rtcode": "5000"}


def get(stocks, retry=3):
    # Prepare data
    data = get_raw(stocks) if not mock else twstock.mock.get(stocks)

    # Set success
    data["success"] = False

    # JSONdecode error, could be too fast, retry
    if data["rtcode"] == "5000":
        # XXX: Stupit retry, you will dead here
        if retry:
            return get(stocks, retry - 1)
        return data

    # No msgArray, dead
    if "msgArray" not in data:
        return data

    # Check have data
    if not len(data["msgArray"]):
        data["rtmessage"] = "Empty Query."
        data["rtcode"] = "5001"
        return data

    # Return multiple stock data
    if isinstance(stocks, list):
        result = {
            data["info"]["code"]: data
            for data in map(_format_stock_info, data["msgArray"])
        }
        result["success"] = True
        return result

    return _format_stock_info(data["msgArray"][0])
