###
# Copyright (c) 2018, cottongin
# Copyright (c) 2020, oddluck <oddluck@riseup.net>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#   * Redistributions of source code must retain the above copyright notice,
#     this list of conditions, and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright notice,
#     this list of conditions, and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#   * Neither the name of the author of this software nor the name of
#     contributors to this software may be used to endorse or promote products
#     derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###

import requests
import pendulum
import json
from supybot import utils, plugins, ircutils, callbacks
from supybot.commands import *

try:
    from supybot.i18n import PluginInternationalization

    _ = PluginInternationalization("Odds")
except ImportError:
    # Placeholder that allows to run the plugin on a bot
    # without the i18n module
    _ = lambda x: x


class Odds(callbacks.Plugin):
    """Fetches odds"""

    threaded = True

    def __init__(self, irc):
        self.__parent = super(Odds, self)
        self.__parent.__init__(irc)

    @wrap(
        [
            getopts(
                {
                    "nfl": "",
                    "mlb": "",
                    "nhl": "",
                    "nba": "",
                    "cfb": "",
                    "cbb": "",
                    "NFL": "",
                    "MLB": "",
                    "NHL": "",
                    "NBA": "",
                    "CFB": "",
                    "CBB": "",
                }
            ),
            optional("text"),
        ]
    )
    def odds(self, irc, msg, args, optlist, opttext=None):
        """--<league> [<team>]
        Fetches odds for given league with an optional team to filter
        """

        optlist = dict(optlist)
        # print(optlist)
        validLeagues = ["--NFL", "--MLB", "--NHL", "--NBA", "--CFB", "--CBB"]
        leagueMap = {"cfb": 1, "nfl": 2, "mlb": 3, "nba": 4, "cbb": 5, "nhl": 6}
        idMap = {"1": "CFB", "2": "NFL", "3": "MLB", "4": "NBA", "5": "CBB", "6": "NHL"}

        if not optlist:
            irc.reply(
                "Error: Must provide a valid league. Valid leagues are: {}".format(
                    ", ".join(x for x in validLeagues)
                )
            )
            return

        leagues = []
        outputLeagues = []
        for key, value in optlist.items():
            league = key.lower() if value == True else None
            if league:
                leagues.append(leagueMap[league])
                outputLeagues.append(idMap[str(leagueMap[league])])

        base_url = (
            "https://therundown.io/api/v1/sports/{league}/events/{date}?offset=300"
        )
        data = []
        today = pendulum.now("US/Pacific").format("YYYY-MM-DD")
        tdate = pendulum.now("US/Pacific")

        # if 6 in leagues:
        #    dates = [tdate.add(days=1).format('YYYY-MM-DD')]
        for idx, league in enumerate(leagues):
            # print(league)
            if league == 6:
                # print('one')
                headers = {
                    "accept": "application/json, text/plain, */*",
                    "accept-encoding": "gzip, deflate, br",
                    "accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
                    "origin": "https://www.oddsshark.com/",
                    "referer": "https://www.oddsshark.com/nhl/odds",
                    "user-agent": (
                        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML,"
                        " like Gecko) Chrome/69.0.3497.100 Safari/537.36"
                    ),
                }

                request = requests.get(
                    "https://io.oddsshark.com/ticker/nhl", headers=headers
                )
                request = json.loads(request.content)
                data.append(request)

            elif league == 4:
                # print('one')
                headers = {
                    "accept": "application/json, text/plain, */*",
                    "accept-encoding": "gzip, deflate, br",
                    "accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
                    "origin": "https://www.oddsshark.com/",
                    "referer": "https://www.oddsshark.com/nba/odds",
                    "user-agent": (
                        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML,"
                        " like Gecko) Chrome/69.0.3497.100 Safari/537.36"
                    ),
                }

                request = requests.get(
                    "https://io.oddsshark.com/ticker/nba", headers=headers
                )
                request = json.loads(request.content)
                data.append(request)
            else:
                # print('two')
                url = base_url.format(league=league, date=today)

                headers = {
                    "accept": "application/json, text/plain, */*",
                    "accept-encoding": "gzip, deflate, br",
                    "accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
                    "origin": "https://www.oddsshark.com/",
                    "user-agent": (
                        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML,"
                        " like Gecko) Chrome/69.0.3497.100 Safari/537.36"
                    ),
                }

                request = requests.get(url, timeout=10, headers=headers)
                request = json.loads(request.content)
                data.append(request)

                if league == 2 or league == 1 or league == 3:
                    if league == 2 or league == 1:
                        dates = [
                            tdate.add(days=1).format("YYYY-MM-DD"),
                            tdate.add(days=2).format("YYYY-MM-DD"),
                            tdate.add(days=3).format("YYYY-MM-DD"),
                            tdate.add(days=4).format("YYYY-MM-DD"),
                            tdate.add(days=5).format("YYYY-MM-DD"),
                            tdate.add(days=6).format("YYYY-MM-DD"),
                        ]
                    if league == 3:
                        dates = [
                            tdate.add(days=1).format("YYYY-MM-DD"),
                            tdate.add(days=2).format("YYYY-MM-DD"),
                            tdate.add(days=3).format("YYYY-MM-DD"),
                            tdate.add(days=4).format("YYYY-MM-DD"),
                        ]
                    #                     if league == 6:
                    #                         dates
                    for nflday in dates:
                        url = base_url.format(league=league, date=nflday)
                        # print(url)
                        request = requests.get(url)
                        request = json.loads(request.content)
                        data[idx]["events"].extend(request["events"])
        # print(data)
        #
        # try:
        #             print(data[0], data[1])
        #         except:
        #             pass

        cleaned_data = self._parseData(data, opttext, leagues)

        if not cleaned_data:
            irc.reply("Error: No odds found for that query")
            return

        cleaned_data = self._sortData(cleaned_data)

        # print(outputLeagues)
        for idx, item in enumerate(cleaned_data):
            if item:
                if "Games with" not in item:
                    if len(item) > 8:
                        if len(item) > 16:
                            split = len(item) // 3
                            irc.reply(
                                "\x02{}:\x02 {}".format(
                                    outputLeagues[idx],
                                    " | ".join(x for x in item[:split]),
                                )
                            )
                            irc.reply(
                                "{}".format(
                                    " | ".join(x for x in item[split : split + split])
                                )
                            )
                            irc.reply(
                                "{}".format(
                                    " | ".join(x for x in item[split + split :])
                                )
                            )
                            return
                        split = len(item) // 2
                        irc.reply(
                            "\x02{}:\x02 {}".format(
                                outputLeagues[idx], " | ".join(x for x in item[:split])
                            )
                        )
                        irc.reply("{}".format(" | ".join(x for x in item[split:])))
                    else:
                        irc.reply(
                            "\x02{}:\x02 {}".format(
                                outputLeagues[idx], " | ".join(x for x in item)
                            )
                        )
                else:
                    irc.reply(item)
            else:
                irc.reply(
                    "\x02{}:\x02 {}".format(
                        outputLeagues[idx], "No results found for that query"
                    )
                )

    def _parseData(self, data, team, leagues, tz=None):

        new_data = []

        # print(len(data['events']))
        # print(len(data))

        for idx, item in enumerate(data):
            # print(leagues[idx])
            if leagues[idx] in [4, 6]:
                if leagues[idx] == 6:
                    translate_team = {
                        "WAS": "WSH",
                        "MON": "MTL",
                        "CLB": "CBJ",
                        "NJ": "NJD",
                        "SJ": "SJS",
                        "LA": "LAK",
                        "TB": "TBL",
                        "NAS": "NSH",
                        "CAL": "CGY",
                    }
                else:
                    translate_team = {
                        "CHR": "CHA",
                        "NY": "NYK",
                        "SAN": "SAS",
                        "PHO": "PHX",
                    }
                # print(item)
                today = pendulum.now()
                tmp_data = []
                no_odds_str = "Games with no odds yet: "
                no_odds = []
                for event in item["matchups"]:
                    if event["type"] != "matchup":
                        continue
                    date = pendulum.parse(event["event_date"]).format("M/D h:mm A")
                    home = (
                        event["home_short_name"]
                        if event["home_short_name"] not in translate_team
                        else translate_team[event["home_short_name"]]
                    )
                    away = (
                        event["away_short_name"]
                        if event["away_short_name"] not in translate_team
                        else translate_team[event["away_short_name"]]
                    )
                    shome = home
                    saway = away
                    home_spread = ""
                    away_spread = ""
                    if event["away_odds"]:
                        if float(event["away_odds"]) < 0:
                            saway = ircutils.bold(away)
                        elif float(event["home_odds"]) < 0:
                            shome = ircutils.bold(home)
                    ou = "-" if not event["total"] else event["total"]

                    ml = "{}/{}".format(
                        "-"
                        if not event["away_odds"]
                        else self._colorize(
                            float(event["away_odds"]), float(event["home_odds"])
                        ),
                        "-"
                        if not event["home_odds"]
                        else self._colorize(
                            float(event["home_odds"]), float(event["away_odds"])
                        ),
                    )
                    string = "{}{} @ {}{} ↕{} {} ({})".format(
                        saway, away_spread, shome, home_spread, ou, ml, date
                    )
                    if (
                        ou == "-"
                        and ml == "-/-"
                        and (
                            today.format("YYYY-MM-DD") in event["event_date"]
                            or today.add(days=1).format("YYYY-MM-DD")
                            in event["event_date"]
                        )
                        and not team
                    ):
                        no_odds.append("{} @ {}".format(away, home))
                    if team:
                        if (
                            today.format("YYYY-MM-DD") in event["event_date"]
                            or today.add(days=1).format("YYYY-MM-DD")
                            in event["event_date"]
                        ):
                            if (
                                team.lower() == home.lower()
                                or team.lower() == away.lower()
                            ):
                                if ou != "-" and ml != "-/-":
                                    tmp_data.append(string)
                    else:
                        if (
                            today.format("YYYY-MM-DD") in event["event_date"]
                            or today.add(days=1).format("YYYY-MM-DD")
                            in event["event_date"]
                        ):
                            if ou != "-" and ml != "-/-":
                                tmp_data.append(string)
                if tmp_data:
                    #                     if no_odds:
                    #                         tmp_data.append('{}{}'.format(no_odds_str, ', '.join(i for i in no_odds)))
                    new_data.append(tmp_data)
                    if no_odds:
                        new_data.append(
                            "{}{}".format(no_odds_str, ", ".join(i for i in no_odds))
                        )
                else:
                    new_data.append(None)
            else:
                tmp_data = []
                # print(len(item['events']))
                for event in item["events"]:
                    # aff_id = '7' # default id
                    aff_id = None
                    for aff in event["lines"]:
                        if (
                            "Bookmaker"
                            in event["lines"][aff]["affiliate"]["affiliate_name"]
                        ):
                            aff_id = aff
                    if not aff_id:
                        for aff in event["lines"]:
                            aff_id = aff
                            break
                    if leagues[idx] == 2 or leagues[idx] == 1 or leagues[idx] == 3:
                        if tz:
                            date = (
                                pendulum.parse(event["event_date"])
                                .in_tz(tz)
                                .format("M/D h:mm A zz")
                            )
                        else:
                            date = (
                                pendulum.parse(event["event_date"])
                                .in_tz("US/Eastern")
                                .format("M/D h:mm A")
                            )
                    else:
                        if tz:
                            date = (
                                pendulum.parse(event["event_date"])
                                .in_tz(tz)
                                .format("h:mm A zz")
                            )
                        else:
                            date = (
                                pendulum.parse(event["event_date"])
                                .in_tz("US/Eastern")
                                .format("h:mm A")
                            )
                    home = event["teams_normalized"][1]["abbreviation"]
                    away = event["teams_normalized"][0]["abbreviation"]
                    home_name = event["teams_normalized"][1]["name"]
                    away_name = event["teams_normalized"][0]["name"]
                    check_spread = False
                    eventdate = pendulum.parse(
                        event["lines"][aff_id]["spread"]["date_updated"], strict=False
                    ).int_timestamp
                    updated = pendulum.parse(
                        event["event_date"], strict=False
                    ).int_timestamp
                    # print(eventdate, updated)
                    if (
                        pendulum.parse(
                            event["lines"][aff_id]["spread"]["date_updated"],
                            strict=False,
                        ).int_timestamp
                        > pendulum.parse(
                            event["event_date"], strict=False
                        ).int_timestamp
                    ):
                        if leagues[idx] == 3:
                            check_spread == True
                    if leagues[idx] != 3 and team:
                        home_spread = "[{}]".format(
                            self._parseSpread(
                                event["lines"][aff_id]["spread"]["point_spread_home"]
                            )
                        )
                        away_spread = "[{}]".format(
                            self._parseSpread(
                                event["lines"][aff_id]["spread"]["point_spread_away"]
                            )
                        )
                    else:
                        home_spread = ""
                        away_spread = ""
                    saway = away
                    shome = home
                    if check_spread:
                        moneyline_away = event["lines"][aff_id]["spread"][
                            "point_spread_away_money"
                        ]
                        moneyline_home = event["lines"][aff_id]["spread"][
                            "point_spread_home_money"
                        ]
                    else:
                        moneyline_away = event["lines"][aff_id]["moneyline"][
                            "moneyline_away"
                        ]
                        moneyline_home = event["lines"][aff_id]["moneyline"][
                            "moneyline_home"
                        ]

                    if moneyline_away < 0:
                        saway = ircutils.bold(away)
                    elif moneyline_home < 0:
                        shome = ircutils.bold(home)
                    # print(event['lines'])
                    ou = (
                        "-"
                        if event["lines"][aff_id]["total"]["total_over"] == 0.0001
                        else event["lines"][aff_id]["total"]["total_over"]
                    )
                    ml = "{}/{}".format(
                        self._colorize(moneyline_away, moneyline_home),
                        self._colorize(moneyline_home, moneyline_away),
                    )
                    string = "{}{} @ {}{} ↕{} {} ({})".format(
                        saway, away_spread, shome, home_spread, ou, ml, date
                    )
                    if team:
                        print(team.lower(), home_name.lower(), away_name.lower())
                        if (
                            team.lower() == home.lower() or team.lower() == away.lower()
                        ) or (
                            team.lower() == home_name.lower()
                            or team.lower() == away_name.lower()
                        ):
                            if ou != "-" and ml != "-/-":
                                tmp_data.append(string)
                    else:
                        if ou != "-" and ml != "-/-":
                            tmp_data.append(string)
                # print(tmp_data)
                if tmp_data:
                    new_data.append(tmp_data)
                else:
                    new_data.append(None)

        # print(new_data)

        return new_data

    def _sortData(self, data):
        # print(data)
        for item in data:
            # print(item)
            if item:
                if "Games with" not in item:
                    # tmp = None
                    # for game in item:
                    #    if 'Games with' in game:
                    #        tmp = item.pop()
                    item.sort(
                        key=lambda x: pendulum.parse(
                            x.split("(")[1].replace(")", ""), strict=False
                        ).int_timestamp
                    )
                # if tmp:
                #    item.append(tmp)

        return data

    def _parseSpread(self, number):
        if number == 0.0001:
            number = 0
        if number > 0:
            number = "+{}".format(number)
        else:
            number = number

        return number

    def _colorize(self, number, vs):
        if number == 0.0001:
            return "-"
        if number > 0:
            number = "+{}".format(number)
            number = ircutils.mircColor(number, "red")
        elif number < 0:
            if vs < 0:
                if number < vs:
                    number = "{}".format(number)
                    number = ircutils.mircColor(number, "green")
                else:
                    number = "{}".format(number)
                    number = ircutils.mircColor(number, "red")
            else:
                number = "{}".format(number)
                number = ircutils.mircColor(number, "green")
        else:
            number = number

        return number


Class = Odds


# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
