# MLBScores
###
# Copyright (c) 2018, cottongin
# 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 supybot.utils as utils
from supybot.commands import *
import supybot.plugins as plugins
import supybot.ircutils as ircutils
import supybot.callbacks as callbacks
import supybot.ircmsgs as ircmsgs
import supybot.schedule as schedule
try:
    from supybot.i18n import PluginInternationalization
    _ = PluginInternationalization('MLBScores')
except ImportError:
    # Placeholder that allows to run the plugin on a bot
    # without the i18n module
    _ = lambda x: x

import requests
import httplib2
import pendulum
import re
import datetime
import pytz
import time
import dateutil.parser
import urllib
import collections
import jellyfish
from operator import itemgetter

from . import inputParser
# from pprint import pprint
# from pybaseball import playerid_lookup
# from pybaseball import pitching_stats_bref
# from pybaseball import batting_stats_bref


class MLBScores(callbacks.Plugin):
    """Plugin to fetch MLB scores from the MLB.com API"""
    threaded = True

    def dprint(self, thing, override=False):
        """debug print"""
        if self._DEBUG == True or override:
            print(thing)
        return
    
    def __init__(self, irc):
        self.__parent = super(MLBScores, self)
        self.__parent.__init__(irc)
        
        self._DEBUG = False
        
        try:
            self.GOOG = irc.getCallback('Google')
        except:
            self.GOOG = None

        self._HTTP = httplib2.Http('.cache')

        self._SCOREBOARD_ENDPOINT = ('https://statsapi.mlb.com/api/v1/schedule'
                                     '?sportId=1,51&date={}'
                                     '&hydrate=team(leaders(showOnPreview('
                                     'leaderCategories=[homeRuns,runsBattedIn,'
                                     'battingAverage],statGroup=[pitching,'
                                     'hitting]))),linescore(matchup,runners),'
                                     'flags,liveLookin,review,broadcasts(all),'
                                     'decisions,person,probablePitcher,stats,'
                                     'homeRuns,previousPlay,game(content('
                                     'media(featured,epg),summary),tickets),'
                                     'seriesStatus(useOverride=true)')

        self._FUZZY_DAYS = ['yesterday', 'tonight', 'today', 'tomorrow',
                            'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']

        #pendulum.set_formatter('alternative')

        self._TEAM_BY_TRI, self._TEAM_BY_ID = self._getTeams()
        self._51_BY_TRI, self._51_BY_ID = self._get51Teams()
        
        self._STATUSES = self._getStatuses()
        #self._ACTIVE_PLAYERS = self._fetchActivePlayers()

        self._TEAM_BY_NICK = {'fish': 'MIA', 'poop': 'NYY', 'goat': 'BOS',
                              'best': 'BOS', 'worst': 'NYY', '💩': 'NYY'}
        
        self._player_aliases = {'buttholz':       'Clay Buchholz',
                                'sucker punch':   'Gary Sanchez',
                                'sucker puncher': 'Gary Sanchez',
                                'big sexy':       'Bartolo Colon',
                                'sexx dragon':    'Joe Mauer',
                                'big papi':       'David Ortiz',
                                'dp':             'dustin pedroia',
                                'lil dp':         'dustin pedroia',
                                'panda':          'pablo sandoval',
                                'gap tooth':      'aaron judge',
                                'jv':             'justin verlander',
                                'comebacker':     'justin verlander',
                                'justdongs':      'jd martinez',
                                'justdongers':    'jd martinez',
                                'erod':           'eduardo rodriguez',
                                'jdmart':         'jd martinez',
                                'starlord':       'alex wilson',
                                'machado':        'dixon machado',
                                'douchebag':      'manny machado',
                                'strikeouts mcgee': 'giancarlo stanton',
                                'k machine':      'giancarlo stanton',
                                'swings and misses': 'giancarlo stanton',
                                'calendario':     'candelario',
                                'scrabble':       'marc rzepczynski',
                                'mr_pink':        'Enyel De Los Santos',
                                'jbj':            'jackie bradley jr.',
                                'mvp':            'mookie betts',
                                'tyler austin\'s daddy': 'joe kelly',
                                'tyler austins daddy': 'joe kelly',
                                'joe kelly\'s son': 'tyler austin',
                                'joe kellys son': 'tyler austin',
                                'joe kelly\'s daughter': 'tyler austin',
                                'joe kellys daughter': 'tyler austin',
        }
        
        def periodicCheckGames():
            #print('MLBScores: Periodic check')
            self.MLB_GAMES = self._fetchGames(None, None)
            #print(self.CFB_GAMES)
            
        def periodicCheckPlayers():
            self._PLAYERS = {}
            self._PLAYERS['active'] = self._fetchPlayers()
            self._PLAYERS['allTime'] = self._fetchPlayers('allTime')
            
        periodicCheckGames()
        periodicCheckPlayers()
        
        try:  # check scores.
            schedule.addPeriodicEvent(periodicCheckGames, 20, now=False, name='fetchMLBscores')
        except AssertionError:
            try:
                schedule.removeEvent('fetchMLBscores')
            except KeyError:
                pass
            schedule.addPeriodicEvent(periodicCheckGames, 20, now=False, name='fetchMLBscores')
            
        try:  # check active rosters.
            schedule.addPeriodicEvent(periodicCheckPlayers, 3600, now=False, name='fetchMLBplayers')
        except AssertionError:
            try:
                schedule.removeEvent('fetchMLBplayers')
            except KeyError:
                pass
            schedule.addPeriodicEvent(periodicCheckPlayers, 3600, now=False, name='fetchMLBplayers')
            
        try:
            schedule.removeEvent('fetchALLMLBplayers')
        except KeyError:
            pass
        
    def _shortenUrl(self, url):
        """Shortens a long URL into a short one."""
        
        # Get a API key from bit.ly
        api_key = self.registryValue('bitlyAPIKey')
        
        url_enc = urllib.parse.quote_plus(url)
        api_url = 'https://api-ssl.bitly.com/v3/shorten?access_token={}&longUrl={}&format=txt'

        try:
            url = requests.get(api_url.format(api_key, url_enc))
            return url.text.strip()
        except:
            return url

    def _getTeams(self, league=None):
        """fetches teams and tricodes"""
        
        if not league:
            url = 'https://statsapi.mlb.com/api/v1/teams?sportId=1'
        else:
            url = 'https://statsapi.mlb.com/api/v1/teams?sportIds={}&leagueId={}'.format(league[0], league[1])

        data = requests.get(url).json()

        tmp1 = {}
        tmp2 = {}
        for team in data['teams']:
            tmp1[team['abbreviation']] = team['id']
            tmp2[str(team['id'])] = team['abbreviation']
        
        return tmp1, tmp2
    
    def _get51Teams(self):
        """fetches teams and tricodes"""

        url = 'https://statsapi.mlb.com/api/v1/teams?sportId=51'

        data = requests.get(url).json()

        tmp1 = {}
        tmp2 = {}
        for team in data['teams']:
            tmp1[team['abbreviation']] = team['id']
            tmp2[str(team['id'])] = team['abbreviation']
        
        return tmp1, tmp2

    def _getStatuses(self):

        url = 'http://statsapi.mlb.com/api/v1/gameStatus'

        data = requests.get(url).json()

        tmp = {}
        for status in data:
            tmp[status['statusCode']] = status['detailedState']

        return tmp
    
    @wrap(['text'])
    def recap(self, irc, msg, args, irc_args):
        """<team> [<date>]
        Returns MLB Recap Videos
        """

        team, date, tz = self._parseInput(irc_args)
        date = pendulum.parse(date)
        if date is None:
            date = datetime.datetime.now().strftime("%y-%m-%d")
            hdate = datetime.datetime.now().strftime("%m/%d/%y")
        else:
#             team, date, tz = self._parseInput(irc_args)
#             for form in ["%d%b", "%d %b", "%b%d", "%b %d", "%d%B", "%d %B", "%b%B", "%b %B", "%B %d", "%B%d", "%Y%m%d", "%Y-%m-%d", "%m%d"]:
#                 result = self.api_get_date(date, form)
#                 if result is not None:
#                     break
#             if result is None:
#                 return("Use the following format: Apr10 or 10Apr or YYYYMMDD")

            day = str(date.day)
            month = str(date.month)
            year = date.year

            if year == 1900:
                year = 2019

            if (year < 2016):
                irc.reply("Sorry, the API only back dates until 2016")
                return
            if len(day) == 1:
                day = "0{}".format(day)
            if len(month) == 1:
                month = "0{}".format(month)

            date = "{}-{}-{}".format(year, month, day)
            hdate = "{}/{}/{}".format(month, day, str(year)[2:])

        #team = self.MLBFindTeam(team.upper(), 0)
#         if len(team) > 3:
#             irc.reply(team)
#             return
        #print(team)
        url = "https://statsapi.mlb.com/api/v1/schedule?sportId=1&date={}&hydrate=linescore(matchup,runners),game(content(media(featured,epg),summary),tickets)&teamId={}".format(date, team)
        content = requests.get(url).json()
        recap = False
        try:
            for each in content['dates'][0]['games']:
                home = int(each['teams']['home']['team']['id'])
                away = int(each['teams']['away']['team']['id'])
                #print(team, home, away)
                if int(team) == home or int(team) == away:
                    newurl = "https://statsapi.mlb.com/api/v1/game/{}/content".format(each['gamePk'])
                    newcontent = requests.get(newurl).json()
                    url = newcontent['media']['epgAlternate'][4]['items'][0]['playbacks'][3]['url']
                    duration = newcontent['media']['epgAlternate'][4]['items'][0]['duration']
                    duration = datetime.datetime.strptime(duration, "%H:%M:%S").strftime("%Mm%Ss").lstrip("0").lstrip("m")
                    away_s = each['teams']['away']['score']
                    home_s = each['teams']['home']['score']
                    headline = "{} {} @ {} {}".format(self._TEAM_BY_ID[str(away)], away_s, self._TEAM_BY_ID[str(home)], home_s)
                    blurb = newcontent['media']['epgAlternate'][4]['items'][0]['blurb']
                    date, info = blurb.split(":")
                    url = self._shortenUrl(url)
                    irc.reply("\x02Recap: {}\x02 |{}".format(headline, info))
                    recap = True
                    for items in newcontent['media']['epgAlternate'][4]['items'][0]['playbacks']:
                        if items['name'] == 'FLASH_2500K_1280X720':
                            mp4 = self._shortenUrl(items['url'])
                        if items['name'] == 'HTTP_CLOUD_WIRED_WEB':
                            hls = self._shortenUrl(items['url'])
                    irc.reply("\x02MP4\x02: {} | \x02HLS\x02: {} | \x02{}\x02".format(mp4, hls, duration))
        except Exception as e:
            #print(e)
            irc.reply("\x02{}\x02: No recap video available for {}".format(hdate, self._TEAM_BY_ID[team]))

    @wrap
    def mlbwildcard(self, irc, msg, args):
        """Fetches wildcard standings for MLB"""
        
        url = 'https://statsapi.mlb.com/api/v1/standings?leagueId=103,104&season={season}&standingsTypes=wildCard&hydrate=division,conference,sport,league,team(nextSchedule(team,gameType=[R,F,D,L,W,C],inclusive=false),previousSchedule(team,gameType=[R,F,D,L,W,C],inclusive=true))'
        season = pendulum.now().year
        url = url.format(season=season)
        
        try:
            data = requests.get(url)
            data = data.json()
        except:
            irc.reply('Error fetching standings')
            return
        
        al_data = data['records'][0]
        nl_data = data['records'][1]
        
        alwc = []
        nlwc = []
        
        al = self._blue(self._bold(al_data['league']['abbreviation'] + 'WC'))
        nl = self._red(self._bold(nl_data['league']['abbreviation'] + 'WC'))
        
        # BOS +2.5 (W-L) W2 | NYY - (W-L) W2 | 
        
        for team in al_data['teamRecords']:
            string = '{} {} {} {}{}'
            string = string.format(
                self._bold('{:3}'.format(team['team']['abbreviation'])),
                '-' + team['wildCardGamesBack'] if ('-' not in team['wildCardGamesBack'] and '+' not in team['wildCardGamesBack']) else team['wildCardGamesBack'],
                '({}-{})'.format(team['wins'], team['losses']),
                self._green(team['streak']['streakCode']) if 'W' in team['streak']['streakCode'] else self._red(team['streak']['streakCode']),
                ' E#{}'.format(team['wildCardEliminationNumber']) if '-' not in team['wildCardEliminationNumber'] else ''
            )
            if team['wildCardEliminationNumber'] != 'E':
                alwc.append(string)
            
        for team in nl_data['teamRecords']:
            string = '{} {} {} {}{}'
            string = string.format(
                self._bold('{:3}'.format(team['team']['abbreviation'])),
                '-' + team['wildCardGamesBack'] if ('-' not in team['wildCardGamesBack'] and '+' not in team['wildCardGamesBack']) else team['wildCardGamesBack'],
                '({}-{})'.format(team['wins'], team['losses']),
                self._green(team['streak']['streakCode']) if 'W' in team['streak']['streakCode'] else self._red(team['streak']['streakCode']),
                ' E#{}'.format(team['wildCardEliminationNumber']) if '-' not in team['wildCardEliminationNumber'] else ''
            )
            if team['wildCardEliminationNumber'] != 'E':
                nlwc.append(string)
            
        al_string = '{}: {}'.format(al, ' | '.join(string for string in alwc))
        nl_string = '{}: {}'.format(nl, ' | '.join(string for string in nlwc))
        irc.reply(al_string)
        irc.reply(nl_string)
    
    
    @wrap([optional('text')])
    def mlbstandings(self, irc, msg, args, irc_args=None):
        """[<division>]
        Fetches standings for given division, defaults to all divisions if not provided
        """
        
        valid_leagues = ['ALE', 'ALW', 'ALC',
                         'NLE', 'NLW', 'NLC']
        table = False
        if irc_args:
            if '--table' in irc_args:
                table = True
                irc_args = irc_args.replace('--table', '')
                irc_args = irc_args.strip()
            if irc_args.upper() not in valid_leagues:
                irc.reply('Error: invalid league')
                return
        
        now = pendulum.now().year
        url = ('https://statsapi.mlb.com/api/v1/standings?leagueId=103,104'
               '&season={season}&standingsTypes=regularSeason'
               '&hydrate=division,conference,sport,league,team'
               '(nextSchedule(team,gameType=[R,F,D,L,W,C],inclusive=false),'
               'previousSchedule(team,gameType=[R,F,D,L,W,C],inclusive=true))')
        url = url.format(season=now)
        
        try:
            data = requests.get(url)
            data = data.json()
        except:
            irc.reply('Error fetching standings')
            return
        
        #print(data['records'][0])
        
        data = data['records']
        
        # ALE: BOS - (103-50) L2 | NYY -10 (94-50) W2 | 
        
        standings = collections.OrderedDict()
        divisions = {}
        for league in data:
            abbrv = league['division']['abbreviation']
            short_name = league['division']['nameShort']
            divisions[abbrv] = short_name
            standings[abbrv] = []
            for team in league['teamRecords']:
                tmp = collections.OrderedDict()
                tmp['team_abbrv'] = team['team']['abbreviation']
                tmp['games_back'] = team['divisionGamesBack']
                tmp['record'] = '({}-{})'.format(team['wins'], team['losses'])
                tmp['wins'] = team['wins']
                tmp['losses'] = team['losses']
                tmp['streak'] = team['streak']['streakCode']
                tmp['clinched'] = team['clinchIndicator'] if team['clinched'] else ''
                tmp['pct'] = team['leagueRecord']['pct']
                tmp['enum'] = team['eliminationNumber']
                tmp['wcgb'] = team['wildCardGamesBack']
                for split in team['records']['splitRecords']:
                    if 'lastTen' in split['type']:
                        tmp['last10'] = '{}-{}'.format(split['wins'], split['losses'])
                tmp['rs'] = team['runsScored']
                tmp['ra'] = team['runsAllowed']
                tmp['diff'] = team['runDifferential']
                tmp['xwl'] = '{}-{}'.format(team['records']['expectedRecords'][0]['wins'], team['records']['expectedRecords'][0]['losses'])
                tmp['home'] = '{}-{}'.format(team['records']['splitRecords'][0]['wins'], team['records']['splitRecords'][0]['losses'])
                tmp['away'] = '{}-{}'.format(team['records']['splitRecords'][1]['wins'], team['records']['splitRecords'][1]['losses'])
                tmp['.500'] = '{}-{}'.format(team['records']['splitRecords'][7]['wins'], team['records']['splitRecords'][7]['losses'])
                try:
                    if team['team']['abbreviation'] == team['team']['nextGameSchedule']['dates'][0]['games'][0]['teams']['away']['team']['abbreviation']:
                        nextStr = 'at {}'.format(team['team']['nextGameSchedule']['dates'][0]['games'][0]['teams']['home']['team']['abbreviation'])
                    else:
                        nextStr = 'vs {}'.format(team['team']['nextGameSchedule']['dates'][0]['games'][0]['teams']['away']['team']['abbreviation'])
                    tmp['next'] = '{} {}'.format(
                        pendulum.parse(team['team']['nextGameSchedule']['dates'][0]['date']).format('MMM D'),
                        nextStr                    
                    )
                except:
                    tmp['next'] = '-'
                tmp['team'] = team['team']['shortName']
                standings[abbrv].append(tmp)
                
        #print(standings['ALE'][0])
        #print(divisions)
        #irc.reply(standings['ALE']
        for league in standings:
            if not irc_args or (irc_args and not table):
                reply_string = '{}: '.format(self._bold(self._blue(league)) if 'A' in league else self._bold(self._red(league)))
                tmp_strings = []
                for idx, team in enumerate(standings[league]):
                    tmp_string = '{} {} {} {}'.format(
                        self._bold('{:3}'.format(team['team_abbrv'])),
                        '-' + '{:4}'.format(team['games_back']) if '-' not in team['games_back'] else team['games_back'],
                        team['record'],
                        self._green(team['streak']) if 'W' in team['streak'] else self._red(team['streak']))
                    tmp_strings.append(tmp_string)

                reply_string += ' | '.join(string for string in tmp_strings)
                if irc_args:
                    if irc_args.upper() == league:
                        irc.reply(reply_string)
                        return
                else:
                    irc.reply(reply_string)   
            else:
                if irc_args.upper() == league:
                    max_width = 0
                    for team in standings[league]:
                        if max_width < len(team['clinched'] + team['team']):
                            max_width = len(team['clinched'] + team['team'])
                    league_width = max_width - len(divisions[irc_args.upper()]) + 2
                    header = '{}{:{width}} W   L   PCT   GB   E#  WCGB  L10 STRK  RS   RA  DIFF  X-W/L    Home   Away  >.500  Next Game'
                    header = header.format(divisions[irc_args.upper()], ' ', width=league_width)
                    irc.reply(header)
                    for team in standings[league]:
                        reply_string = '{:{width}} {:3} {:3}  {}  {:^4}  {}   {:^4}  {}  {}  {}  {}  {:^4}  {:7} {}  {}  {}  {}'
                        reply_string = reply_string.format(
                            team['clinched'] + team['team'],
                            team['wins'], team['losses'],
                            team['pct'],
                            team['games_back'],
                            team['enum'],
                            team['wcgb'],
                            team['last10'],
                            team['streak'],
                            team['rs'],
                            team['ra'],
                            team['diff'],
                            team['xwl'],
                            team['home'],
                            team['away'],
                            team['.500'],
                            team['next'],
                            width=max_width
                        )
                        irc.reply(reply_string)
    
    @wrap([optional('text')])
    def offseason(self, irc, msg, args, irc_args=None):
        """[<team tri code>] [<date>]
        Fetches scores for given team and/or date. Defaults to today and all
        teams if no input provided"""

        tv = False
        if irc_args:
            if '--tv' in irc_args:
                tv = True
                irc_args = irc_args.replace('--tv','')
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')
                
        team_codes, _ = self._getTeams(league=[17, '119,131,132,133,135,162,516,595'])

        try:
            team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        
        #print('MLBScores: No cached scores, pulling fresh')
        GAMES = self._fetchGames(team, date, league=[17, '119,131,132,133,135,162,516,595'])

        if not GAMES:
            irc.reply('No games found')
            return

        games = self._parseGames(GAMES, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)

        reply_string = self._replyAsString(team, games, tz, tv)

        # what = type(reply_string)
        # print(what)

        # print(reply_string)

        if type(reply_string) is tuple or type(reply_string) is list:
            for string in reply_string:
                irc.reply(string)
        else:
            irc.reply(reply_string)
    
    @wrap([optional('text')])
    def cs(self, irc, msg, args, irc_args=None):
        """[<team tri code>] [<date>]
        Fetches scores for given team and/or date. Defaults to today and all
        teams if no input provided"""

        tv = False
        if irc_args:
            if '--tv' in irc_args:
                tv = True
                irc_args = irc_args.replace('--tv','')
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')
                
        team_codes, _ = self._getTeams(league=[17, 162])

        try:
            team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        
        #print('MLBScores: No cached scores, pulling fresh')
        GAMES = self._fetchGames(team, date, league=[17, 162])

        if not GAMES:
            irc.reply('No games found')
            return

        games = self._parseGames(GAMES, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)

        reply_string = self._replyAsString(team, games, tz, tv)

        # what = type(reply_string)
        # print(what)

        # print(reply_string)

        if type(reply_string) is tuple or type(reply_string) is list:
            for string in reply_string:
                irc.reply(string)
        else:
            irc.reply(reply_string)
    
    @wrap([optional('text')])
    def abl(self, irc, msg, args, irc_args=None):
        """[<team tri code>] [<date>]
        Fetches scores for given team and/or date. Defaults to today and all
        teams if no input provided"""

        tv = False
        if irc_args:
            if '--tv' in irc_args:
                tv = True
                irc_args = irc_args.replace('--tv','')
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')
                
        team_codes, _ = self._getTeams(league=[17, 595])

        try:
            team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        
        #print('MLBScores: No cached scores, pulling fresh')
        GAMES = self._fetchGames(team, date, league=[17, 595])

        if not GAMES:
            irc.reply('No games found')
            return

        games = self._parseGames(GAMES, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)

        reply_string = self._replyAsString(team, games, tz, tv)

        # what = type(reply_string)
        # print(what)

        # print(reply_string)

        if type(reply_string) is tuple or type(reply_string) is list:
            for string in reply_string:
                irc.reply(string)
        else:
            irc.reply(reply_string)
    
    @wrap([optional('text')])
    def winl(self, irc, msg, args, irc_args=None):
        """[<team tri code>] [<date>]
        Fetches scores for given team and/or date. Defaults to today and all
        teams if no input provided"""

        tv = False
        if irc_args:
            if '--tv' in irc_args:
                tv = True
                irc_args = irc_args.replace('--tv','')
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')
                
        team_codes, _ = self._getTeams(league=[17, 516])

        try:
            team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        
        #print('MLBScores: No cached scores, pulling fresh')
        GAMES = self._fetchGames(team, date, league=[17, 516])

        if not GAMES:
            irc.reply('No games found')
            return

        games = self._parseGames(GAMES, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)

        reply_string = self._replyAsString(team, games, tz, tv)

        # what = type(reply_string)
        # print(what)

        # print(reply_string)

        if type(reply_string) is tuple or type(reply_string) is list:
            for string in reply_string:
                irc.reply(string)
        else:
            irc.reply(reply_string)
    
    @wrap([optional('text')])
    def vwl(self, irc, msg, args, irc_args=None):
        """[<team tri code>] [<date>]
        Fetches scores for given team and/or date. Defaults to today and all
        teams if no input provided"""

        tv = False
        if irc_args:
            if '--tv' in irc_args:
                tv = True
                irc_args = irc_args.replace('--tv','')
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')
                
        team_codes, _ = self._getTeams(league=[17, 135])

        try:
            team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        
        #print('MLBScores: No cached scores, pulling fresh')
        GAMES = self._fetchGames(team, date, league=[17, 135])

        if not GAMES:
            irc.reply('No games found')
            return

        games = self._parseGames(GAMES, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)

        reply_string = self._replyAsString(team, games, tz, tv)

        # what = type(reply_string)
        # print(what)

        # print(reply_string)

        if type(reply_string) is tuple or type(reply_string) is list:
            for string in reply_string:
                irc.reply(string)
        else:
            irc.reply(reply_string)
    
    @wrap([optional('text')])
    def pwl(self, irc, msg, args, irc_args=None):
        """[<team tri code>] [<date>]
        Fetches scores for given team and/or date. Defaults to today and all
        teams if no input provided"""

        tv = False
        if irc_args:
            if '--tv' in irc_args:
                tv = True
                irc_args = irc_args.replace('--tv','')
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')
                
        team_codes, _ = self._getTeams(league=[17, 133])

        try:
            team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        
        #print('MLBScores: No cached scores, pulling fresh')
        GAMES = self._fetchGames(team, date, league=[17, 133])

        if not GAMES:
            irc.reply('No games found')
            return

        games = self._parseGames(GAMES, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)

        reply_string = self._replyAsString(team, games, tz, tv)

        # what = type(reply_string)
        # print(what)

        # print(reply_string)

        if type(reply_string) is tuple or type(reply_string) is list:
            for string in reply_string:
                irc.reply(string)
        else:
            irc.reply(reply_string)
    
    @wrap([optional('text')])
    def lmp(self, irc, msg, args, irc_args=None):
        """[<team tri code>] [<date>]
        Fetches scores for given team and/or date. Defaults to today and all
        teams if no input provided"""

        tv = False
        if irc_args:
            if '--tv' in irc_args:
                tv = True
                irc_args = irc_args.replace('--tv','')
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')
                
        team_codes, _ = self._getTeams(league=[17, 132])

        try:
            team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        
        #print('MLBScores: No cached scores, pulling fresh')
        GAMES = self._fetchGames(team, date, league=[17, 132])

        if not GAMES:
            irc.reply('No games found')
            return

        games = self._parseGames(GAMES, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)

        reply_string = self._replyAsString(team, games, tz, tv)

        # what = type(reply_string)
        # print(what)

        # print(reply_string)

        if type(reply_string) is tuple or type(reply_string) is list:
            for string in reply_string:
                irc.reply(string)
        else:
            irc.reply(reply_string)
    
    @wrap([optional('text')])
    def dwl(self, irc, msg, args, irc_args=None):
        """[<team tri code>] [<date>]
        Fetches scores for given team and/or date. Defaults to today and all
        teams if no input provided"""

        tv = False
        if irc_args:
            if '--tv' in irc_args:
                tv = True
                irc_args = irc_args.replace('--tv','')
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')
                
        team_codes, _ = self._getTeams(league=[17, 131])

        try:
            team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        
        #print('MLBScores: No cached scores, pulling fresh')
        GAMES = self._fetchGames(team, date, league=[17, 131])

        if not GAMES:
            irc.reply('No games found')
            return

        games = self._parseGames(GAMES, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)

        reply_string = self._replyAsString(team, games, tz, tv)

        # what = type(reply_string)
        # print(what)

        # print(reply_string)

        if type(reply_string) is tuple or type(reply_string) is list:
            for string in reply_string:
                irc.reply(string)
        else:
            irc.reply(reply_string)
    
    @wrap([optional('text')])
    def azfl(self, irc, msg, args, irc_args=None):
        """[<team tri code>] [<date>]
        Fetches scores for given team and/or date. Defaults to today and all
        teams if no input provided"""

        tv = False
        if irc_args:
            if '--tv' in irc_args:
                tv = True
                irc_args = irc_args.replace('--tv','')
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')
                
        team_codes, _ = self._getTeams(league=[17, 119])

        try:
            team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        
        #print('MLBScores: No cached scores, pulling fresh')
        GAMES = self._fetchGames(team, date, league=[17, 119])

        if not GAMES:
            irc.reply('No games found')
            return

        games = self._parseGames(GAMES, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)

        reply_string = self._replyAsString(team, games, tz, tv)

        # what = type(reply_string)
        # print(what)

        # print(reply_string)

        if type(reply_string) is tuple or type(reply_string) is list:
            for string in reply_string:
                irc.reply(string)
        else:
            irc.reply(reply_string)
    
    
    @wrap([optional('text')])
    def mlb(self, irc, msg, args, irc_args=None):
        """[<team tri code>] [<date>]
        Fetches scores for given team and/or date. Defaults to today and all
        teams if no input provided"""

        tv = False
        if irc_args:
            if '--tv' in irc_args:
                tv = True
                irc_args = irc_args.replace('--tv','')
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')

        team_codes, _ = self._getTeams()
        #print(team_codes)

        try:
            team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        if not self.MLB_GAMES or date:
            #print('MLBScores: No cached scores, pulling fresh')
            self.MLB_GAMES = self._fetchGames(team, date)

        if not self.MLB_GAMES:
            irc.reply('No games found')
            return

        games = self._parseGames(self.MLB_GAMES, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)

        reply_string = self._replyAsString(team, games, tz, tv)

        # what = type(reply_string)
        # print(what)

        # print(reply_string)

        if type(reply_string) is tuple or type(reply_string) is list:
            for string in reply_string:
                irc.reply(string)
        else:
            irc.reply(reply_string)
            
        if date:
            self.MLB_GAMES = self._fetchGames(team)
    
    
    @wrap(['text'])
    def currentab(self, irc, msg, args, irc_args):
        """[<team tri code>]
        Fetches details for current at bat for the given team."""

        if irc_args:
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')

        try:
            team, date, tz = inputParser.parseInput(irc_args, self._TEAM_BY_TRI, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        games = self._fetchGames(team, date)

        if not games:
            irc.reply('No games found')
            return

        games = self._parseGames(games, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)
        
        for game in games:
            at_bat = game['atBat']
            
        if not at_bat:
            irc.reply('ERROR: No current at bat found, game active?')
            return

        irc.reply(at_bat)
        
    @wrap(['positiveInt','text'])
    def findab(self, irc, msg, args, ab_index, irc_args):
        """<ab #> <team tri code>
        Fetches details for current at bat for the given team."""

        if irc_args:
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')

        try:
            team, date, tz = inputParser.parseInput(irc_args, self._TEAM_BY_TRI, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        games = self._fetchGames(team, date)

        if not games:
            irc.reply('No games found')
            return

        games = self._parseGames(games, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)
        
        ab_index = str(ab_index-1)
        for game in games:
            at_bat = game['atBats'].get(ab_index)
            
        if not at_bat:
            irc.reply('ERROR: No at bat found, game active?')
            return
        
        at_bat = at_bat[0]

        irc.reply(at_bat)
        
    @wrap(['text'])
    def atbats(self, irc, msg, args, irc_args):
        """<ab #> <team tri code>
        Fetches details for current at bat for the given team."""

        if irc_args:
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')

        try:
            team, date, tz = inputParser.parseInput(irc_args, self._TEAM_BY_TRI, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        games = self._fetchGames(team, date)

        if not games:
            irc.reply('No games found')
            return

        games = self._parseGames(games, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)
        
        #ab_index = str(ab_index-1)
        at_bats = []
        for game in games:
            for k,v in game['atBats'].items():
                #print(k)
                at_bats.append([v[1], v[2]])
                
            
        if not at_bats:
            irc.reply('ERROR: No at bats found, game active?')
            return
        
        at_bats = sorted(at_bats, key=lambda k: k[0], reverse=True)

        irc.reply(', '.join(str(a[0]) + '-' + a[1] for a in at_bats))
        
    @wrap(['text'])
    def lastatbat(self, irc, msg, args, irc_args):
        """<team> <player>
        Fetches details for last at bat for the given team and player."""

        if irc_args:
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')
                
        player = irc_args.split()[1:]
        player = ' '.join(n for n in player).strip()
        irc_args = irc_args.split()[0]

        try:
            team, date, tz = inputParser.parseInput(irc_args, self._TEAM_BY_TRI, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(irc_args)
            print('internal parser worked')
        #print(team)
        #print(date)

        games = self._fetchGames(team, date)

        if not games:
            irc.reply('No games found')
            return

        games = self._parseGames(games, date, team)
        if not games:
            irc.reply('No games found')
            return
        games = self._sortGames(games)
        
        #ab_index = str(ab_index-1)
        at_bats = []
        for game in games:
            for k,v in game['atBats'].items():
                #print(k)
                at_bats.append([v[1], v[2]])
                
            
        if not at_bats:
            irc.reply('ERROR: No at bats found, game active?')
            return
        
        at_bats = sorted(at_bats, key=lambda k: k[0], reverse=True)
        
        for at_bat in at_bats:
            #print(player.lower(), at_bat[1].lower())
            if player.lower() == at_bat[1].lower():
                print('hi')
                idx = str(at_bat[0]-1)
                for game in games:
                    print(game['atBats'].get(idx), idx)
                    ab = game['atBats'].get(idx)
                    if ab:
                        ab = ab[0]
                break

        irc.reply(ab)
    
    
    def _sanitizeName(self, name):
        """ Sanitize name. """

        name = name.lower()  # lower.
        #name = name.strip('.')  # remove periods.
        name = name.strip('-')  # remove dashes.
        name = name.strip("'")  # remove apostrophies.
        # possibly strip jr/sr/III suffixes in here?
        return name
    
    def _pf(self, db, pname):
        """<e|r|s> <player>

        Find a player's page via google ajax. Specify DB based on site.
        """

        # check for aliases first
        if pname.lower() in self._player_aliases:
            pname = self._player_aliases[pname.lower()]
        # sanitize.
        pname = self._sanitizeName(pname)
        
        # db.
        if db == "e":  # espn.
            #splitsfix = '-site:espn.go.com/mlb/player/splits/'
            burl = "site:espn.go.com/mlb/player/ {0}".format(pname)
        elif db == "r":  # rworld.
            burl = "site:www.rotoworld.com/player/mlb/ %s" % pname
        elif db == "s":  # st.
            burl = "site:www.spotrac.com/mlb/ %s" % pname
        elif db == "br":  # br.
            burl = "site:www.baseball-reference.com/ %s" % pname

        # now actually search
        try:
            #goog = self.GOOG
            if self.GOOG:
                try:
                    search = self.GOOG.search('{0}'.format(burl),'#reddit-baseball',{'smallsearch': True})
                    search = self.GOOG.decode(search)
                    if search:
                        url = search[0]['url']
#                         title = search[0]['title']
#                         title = title.replace('<b>', '')
#                         title = title.replace('</b>', '')
#                         title = title.strip()
#                         if pname.title() in title:
#                             title = title.split(pname.title())[0]
#                             title += pname.title()
#                         else:
#                             title = title.split('-')[0]
#                             title = title.strip()
                        title = url.split('/')[-1]
                        title = title.replace('-', ' ')
                        print(title)
                        return title
                except:
                    self.log.exception("ERROR :: _pf :: failed to get link for {0}".format(burl))
                    return None
        except Exception as e:
            self.log.info("ERROR :: _pf :: {0}".format(e))
            return None
            
    def _similarPlayers(self, optname):
        """Return a dict containing the five most similar players based on optname."""
        
        activeplayers = self._PLAYERS['active']
        # test length as sanity check.
        if len(activeplayers) == 0:
            self.log.info("ERROR: _similarPlayers :: length 0. Could not find any players in players source")
            return None
        # ok, finally, lets go.
        optname = str(self._sanitizeName(optname))  # sanitizename.
        
        jaro, damerau = [], []  # empty lists to put our results in.
        # now we create the container to iterate over.
        names = [{'fullname': str(self._sanitizeName(k)), 'id':v['id']} for k,v in activeplayers.items()]  # full_name # last_name # first_name
        #print(type(optname))
        # iterate over the entries.
        for row in names:  # list of dicts.
            jaroscore = jellyfish.jaro_distance(optname, row['fullname'])  # jaro.
            damerauscore = jellyfish.damerau_levenshtein_distance(optname, row['fullname'])  # dld
            jaro.append({'jaro': jaroscore, 'fullname': row['fullname'], 'id': row['id']})  # add dict to list.
            damerau.append({'damerau': damerauscore, 'fullname': row['fullname'], 'id': row['id']})  # ibid.
        # now, we do two "sorts" to find the "top5" matches. reverse is opposite on each.
        jarolist = sorted(jaro, key=itemgetter('jaro'), reverse=True)[0:5]  # bot five.
        dameraulist = sorted(damerau, key=itemgetter('damerau'), reverse=False)[0:5]  # top five.
        # we now have two lists, top5 sorted, and need to do some further things.
        # now, lets iterate through both lists. match if both are in it. (better matches)
        matching = [k for k in jarolist if k['id'] in [f['id'] for f in dameraulist]]
        # now, test if we have anything. better matches will have more.
        if len(matching) == 0:  # we have NO matches. grab the top two from jaro/damerau (for error str)
            matching = [jarolist[0], dameraulist[0], jarolist[1], dameraulist[1]]
            self.log.info("_similarPlayers :: NO MATCHES for {0} :: {1}".format(optname, matching))
            match = False
        else:
            match = True
        # return matching now.
        return matching, match
    
#     def _fetchActivePlayers(self):
        
#         api_base = 'http://statsapi.mlb.com'
#         roster_url = '/api/v1/teams/{team}/roster/active'
        
#         players = {}
#         for team in self._TEAM_BY_ID:
#             url = api_base + roster_url.format(team=team)
#             #print(url)
#             tmp = requests.get(url).json()
#             for player in tmp['roster']:
#                 if 'Pitcher' in player['position']['type']:
#                     stat_type = 'pitching'
#                 else:
#                     stat_type = 'hitting'
#                 players[player['person']['fullName']] = {'id': player['person']['id'], 
#                                                          'url': player['person']['link'],
#                                                          'team': player['parentTeamId'],
#                                                          'stat': stat_type}
#         self._ACTIVE_PLAYERS = players
#         return players
    
    def _fetchPlayers(self, search_type=None):
        
        # default to active rosters only
        if not search_type:
            search_type = 'active'
        
        api_base = 'http://statsapi.mlb.com'
        roster_url = '/api/v1/teams/{team}/roster/{search_type}'
        
        # build db
        players = {}
        for team in self._TEAM_BY_ID:
            url = api_base + roster_url.format(team=team, search_type=search_type)
            tmp = requests.get(url).json()
            for player in tmp['roster']:
                # assign stat category to fetch
                if 'Pitcher' in player['position']['type']:
                    stat_type = 'pitching'
                else:
                    stat_type = 'hitting'
                # active players will have a team, inactive will not
                try:
                    team = player['parentTeamId']
                except:
                    team = None
                # finally assign the player and info
                players[player['person']['fullName'].lower()] = {'id': player['person']['id'], 
                                                                  'url': player['person']['link'],
                                                                  'team': team,
                                                                  'stat': stat_type,
                                                                  'disp_name': player['person']['fullName'],
                                                                }
        return players
    
    def _playerSearch(self, optplayer, search_type):
        
        similar_players = None
        match = False
        
        if not self._PLAYERS[search_type]:
            players = self._fetchPlayers(search_type)
        else:
            players = self._PLAYERS[search_type]
        
        if optplayer.lower() not in players:
            test = self._pf('e', optplayer)
            if test:
                optplayer = test
            if optplayer.lower() not in players:
                similar_players, match = self._similarPlayers(optplayer.lower())
                #print(similar_players)
                if match:
                    for item in similar_players:
                        if item['fullname'].title() in players:
                            optplayer = item['fullname']
                            break
                if optplayer.lower() not in players:
                    #irc.reply('ERROR: {} not found on any active roster, check spelling/input'.format(optplayer.title()))
                    return None, similar_players
        #print(optplayer)
        if optplayer.lower() not in players:
            #irc.reply('ERROR: {} not found on any active roster, check spelling/input'.format(optplayer.title()))
            return None, similar_players
        
        player = players[optplayer.lower()]
        player['name'] = player['disp_name']
        
        return player, similar_players
    
    @wrap([getopts({'career': '', 'season': 'somethingWithoutSpaces', 
                    'postseason': '', 'stattype': 'somethingWithoutSpaces'}), 'text'])
    def mlbstats(self, irc, msg, args, options, optplayer):
        """<player name>
        Fetches stats for given player. Options: --season <year>, --career, --postseason"""
        
        api_base = 'http://statsapi.mlb.com'
        roster_url = '/api/v1/teams/{team}/roster/allTime'
        stats_url = ('/api/v1/people?'
                     'personIds={personId}'
                     '&season={year}'
                     '&hydrate=stats(group={group},season={year},type={statType},gameType={reg_or_post})')
    
        options = dict(options)
        # defaults
        statType = 'season'
        year = pendulum.now().year
        reg_or_post = 'R'
        blurb = '{} Season Stats'.format(year)
        if not options:
            statType = 'season'
            year = pendulum.now().year
            reg_or_post = 'R'
            blurb = '{} Season Stats'.format(year)
        # parse our options
        else:
            if 'career' in options and 'postseason' in options:
                # we want career postseason stats
                reg_or_post = 'P'
                statType = 'career'
                year = pendulum.now().year
                blurb = '{} Postseason Stats'.format(statType.title())
            elif 'career' in options and 'postseason' not in options:
                # we want career regular season stats
                reg_or_post = 'R'
                statType = 'career'
                year = pendulum.now().year
                blurb = '{} Stats'.format(statType.title())
            elif 'postseason' in options and 'career' not in options and 'season' not in options:
                # we want current season postseason stats
                statType = 'season'
                year = pendulum.now().year
                reg_or_post = 'P'
                blurb = '{} Postseason Stats'.format(year, statType.title())
            elif 'season' in options and 'postseason' in options:
                # we want custom season postseason stats
                if not options['season'].isdigit():
                    year = pendulum.now().year
                    optplayer = '{} {}'.format(options['season'], optplayer)
                else:
                    year = options['season']
                statType = 'season'
                reg_or_post = 'P'
                blurb = '{} Postseason Stats'.format(year, statType.title())
            elif 'season' in options and 'postseason' not in options:
                # we want custom season regular season stats
                if not options['season'].isdigit():
                    # this is a workaround for the @aka/alias functionality 
                    year = pendulum.now().year
                    optplayer = '{} {}'.format(options['season'], optplayer)
                else:
                    year = options['season']
                statType = 'season'
                reg_or_post = 'R'   
                blurb = '{} {} Stats'.format(year, statType.title())
        
        print(options)
        # now let's try to find our player
        player, possibles = self._playerSearch(optplayer, 'allTime')
        if not player and possibles:
            irc.reply("I couldn't find stats for {}".format(optplayer))
            irc.reply("Possible suggestions: {0}".format(" | ".join([i['fullname'].title() for i in possibles])))
            return
        
        optplayer = player['name']
        group = options.get('stattype') or player['stat']
        print(group)
        tmp = requests.get('{}{}'.format(api_base, stats_url.format(personId=player['id'],
                                                                    year=year,
                                                                    statType=statType,
                                                                    group=group,
                                                                    reg_or_post=reg_or_post)))
        print(tmp.url)
        tmp = tmp.json()
        
        if 'stats' not in tmp['people'][0]:
            irc.reply('ERROR: No stats found for {}'.format(optplayer.title()))
            return
        
        stats = tmp['people'][0]['stats']
        try:
            plyr_info = ' (#{} {})'.format(tmp['people'][0]['primaryNumber'],
                                         tmp['people'][0]['primaryPosition']['abbreviation'])
        except:
            plyr_info = ''
            
        try:
            if not tmp['people'][0].get('active'):
                years = ' ({}-{})'.format(tmp['people'][0]['mlbDebutDate'].split('-')[0],
                                          tmp['people'][0]['lastPlayedDate'].split('-')[0])
            else:
                years = ' ({}-)'.format(tmp['people'][0]['mlbDebutDate'].split('-')[0]) #,
                                          #tmp['people'][0]['lastPlayedDate'].split('-')[0])
        except:
            years = ''
            
        blurb += years
        
        hitting_stat_headers, pitching_stat_headers, _ = self._generateStatHeaders('mlbstats')        
        
        out_stats = []
        stats = stats[0]['splits']
        for thing in stats:
            #print(thing)
            stat_line = collections.OrderedDict({})
            if 'numTeams' not in thing:
                try:
                    team = '{}'.format(self._TEAM_BY_ID[str(thing['team']['id'])])
                except:
                    team = ''
            else:
                team = 'Total'
            if team:
                team = '{} :: '.format(self._bu(team))
            if not thing['stat']:
                stat_line['ERROR'] = 'No stats available for {}'.format(optplayer.title())
                break
            if group == 'hitting':
                for s in hitting_stat_headers:
                    #print(s)
                    if s in thing['stat']:
                        try:
                            stat_line[hitting_stat_headers[s]] = thing['stat'][s]
                        except:
                            stat_line[hitting_stat_headers[s]] = None
            elif group == 'pitching':
                for s in pitching_stat_headers:
                    #print(s)
                    if s in thing['stat']:
                        try:
                            stat_line[pitching_stat_headers[s]] = thing['stat'][s]
                        except:
                            stat_line[pitching_stat_headers[s]] = None
        
            stat_string = ' '.join('{}: {}'.format(self._bold(k),v) for k,v in stat_line.items())
            out_stats.append('{}{}'.format(team, stat_string))
        
        irc.reply('{}{} :: {}'.format(self._bold(self._blue(optplayer)), plyr_info, blurb))
        for line in out_stats:
            irc.reply('{}'.format(line))
        
        return
    
    
    @wrap(['text'])
    def fstats(self, irc, msg, args, optplayer):
        """<player name>
        Fetches current/previous game fielding stats for given player"""
        
        api_base = 'http://statsapi.mlb.com'
        roster_url = '/api/v1/teams/{team}/roster/active'
        stats_url_current = '/api/v1/people/{personId}/stats/game/current'
        stats_url_game = '/api/v1/people/{personId}/stats/game/{gamePk}'
        sched_url = ('/api/v1/teams/{teamId}?hydrate=previousSchedule('
                     'gameType=[E,S,R,A,F,D,L,W]),nextSchedule(gameType=[E,S,R,A,F,D,L,W])')
        
        player, possibles = self._playerSearch(optplayer, 'active')
        if not player and possibles:
            irc.reply("I couldn't find stats for {}".format(optplayer))
            irc.reply("Possible suggestions: {0}".format(" | ".join([i['fullname'].title() for i in possibles])))
            return
        
        optplayer = player['name']
        
        current = False
        tmp = requests.get('{}{}'.format(api_base, stats_url_current.format(personId=player['id'])))
        tmp = tmp.json()
        if not tmp['stats']:
            # no current game
            tmp = requests.get('{}{}'.format(api_base, sched_url.format(teamId=player['team']))).json()
            try:
                if tmp['teams'][0]['nextGameSchedule']['dates'][0]['games'][0]['status']['abstractGameState'] == 'Final':
                    gamePk = tmp['teams'][0]['nextGameSchedule']['dates'][0]['games'][0]['gamePk']
                    gameDate = pendulum.parse(tmp['teams'][0]['nextGameSchedule']['dates'][0]['games'][0]['gameDate'],
                                             strict=False).in_tz('US/Eastern').format('MMM Do')
                else:
                    gamePk = tmp['teams'][0]['previousGameSchedule']['dates'][0]['games'][0]['gamePk']
                    gameDate = pendulum.parse(tmp['teams'][0]['previousGameSchedule']['dates'][0]['games'][0]['gameDate'],
                                             strict=False).in_tz('US/Eastern').format('MMM Do')
                url = api_base + stats_url_game.format(personId=player['id'], gamePk=gamePk)
                tmp = requests.get(url).json()
            except:
                irc.reply('ERROR: No current/previous game fielding stats found for {}'.format(optplayer.title()))
                return
        else:
            current = True
            #TBD
            
        
 
            
        if not tmp['stats']:
            irc.reply('ERROR: No current/previous game fielding stats found for {}'.format(optplayer.title()))
            return
        
        stats = []
        for thing in tmp['stats']:
            if 'type' not in thing:
                stats = thing
                break
                
        if not stats:
            irc.reply('ERROR: No current/previous game fielding stats found for {}'.format(optplayer.title()))
            return
        
        _, _, fielding_stat_headers = self._generateStatHeaders('fstats')
        
        stat_line = collections.OrderedDict({})
        for thing in stats['splits']:
            if thing['group'] == 'fielding':
                if not thing['stat']:
                    stat_line['ERROR'] = 'No fielding stats available for {} in current or previous game'.format(optplayer.title())
                    break
                for s in fielding_stat_headers:
                    if s in thing['stat']:
                        try:
                            stat_line[fielding_stat_headers[s]] = thing['stat'][s]
                        except:
                            stat_line[fielding_stat_headers[s]] = None
                try:
                    pct = (stat_line['Put Outs'] + stat_line['Assists']) / stat_line['Chances']
                    stat_line['Fielding'] = '{:.3f}'.format(pct)
                except ZeroDivisionError:
                    pass
        
        stat_string = ' '.join('{}: {}'.format(self._bold(k),v) for k,v in stat_line.items())
        
        irc.reply('{} ({}) {}'.format(self._bold(self._blue(optplayer.title())), gameDate, stat_string))
        
        return
    
    @wrap(['text'])
    def mlbgamestats(self, irc, msg, args, optplayer):
        """<player name>
        Fetches current/previous game stats for given player"""
        
        api_base = 'http://statsapi.mlb.com'
        roster_url = '/api/v1/teams/{team}/roster/active'
        stats_url_current = '/api/v1/people/{personId}/stats/game/current'
        stats_url_game = '/api/v1/people/{personId}/stats/game/{gamePk}'
        sched_url = ('/api/v1/teams/{teamId}?hydrate=previousSchedule('
                     'gameType=[E,S,R,A,F,D,L,W]),nextSchedule(gameType=[E,S,R,A,F,D,L,W])')
        
        player, possibles = self._playerSearch(optplayer, 'active')
        if not player and possibles:
            irc.reply("I couldn't find stats for {}".format(optplayer))
            irc.reply("Possible suggestions: {0}".format(" | ".join([i['fullname'].title() for i in possibles])))
            return
        
        optplayer = player['name']
        
        current = False
        tmp = requests.get('{}{}'.format(api_base, stats_url_current.format(personId=player['id'])))
        print(tmp.url)
        tmp = tmp.json()
        if not tmp['stats']:
            # no current game
            tmp = requests.get('{}{}'.format(api_base, sched_url.format(teamId=player['team'])))
            print(tmp.url)
            tmp = tmp.json()
            statuses = ['Final', 'Live']
            if tmp['teams'][0]['nextGameSchedule']['dates'][0]['games'][0]['status']['abstractGameState'] in statuses:
                gamePk = tmp['teams'][0]['nextGameSchedule']['dates'][0]['games'][0]['gamePk']
                gameDate = pendulum.parse(tmp['teams'][0]['nextGameSchedule']['dates'][0]['games'][0]['gameDate'],
                                         strict=False).in_tz('US/Eastern').format('MMM Do')
            else:
                gamePk = tmp['teams'][0]['previousGameSchedule']['dates'][0]['games'][0]['gamePk']
                gameDate = pendulum.parse(tmp['teams'][0]['previousGameSchedule']['dates'][0]['games'][0]['gameDate'],
                                         strict=False).in_tz('US/Eastern').format('MMM Do')
            url = api_base + stats_url_game.format(personId=player['id'], gamePk=gamePk)
            #irc.reply(url)
            print(url)
            tmp = requests.get(url).json()
        else:
            current = True
            #TBD
            gameDate = pendulum.now().in_tz('US/Eastern').format('MMM Do')
        #print(gamePk)
        
        
            
        if not tmp['stats']:
            irc.reply('ERROR: No current/previous game stats found for {}'.format(optplayer.title()))
            return
        
        stats = []
        for thing in tmp['stats']:
            if 'type' not in thing:
                stats = thing
                break
                
        #print(stats)
        if not stats:
            irc.reply('ERROR: No current/previous game stats found for {}'.format(optplayer.title()))
            return
        
        hitting_stat_headers, pitching_stat_headers, _ = self._generateStatHeaders('mlbgamestats')
        
        stat_line = collections.OrderedDict({})
        for thing in stats['splits']:
            #print(thing)
            if player['stat'] == thing['group']:
                if not thing['stat']:
                    stat_line['ERROR'] = 'No stats available for {} on {}'.format(optplayer.title(), gameDate)
                    break
                if player['stat'] == 'hitting':
                    for s in hitting_stat_headers:
                        #print(s)
                        if s in thing['stat']:
                            try:
                                stat_line[hitting_stat_headers[s]] = thing['stat'][s]
                            except:
                                stat_line[hitting_stat_headers[s]] = None
                    try:
                        avg = stat_line['H'] / stat_line['AB']
                        avg = '{:.3f}'.format(avg)                    
                    except ZeroDivisionError:
                        avg = ''
                    
                    stat_line['AVG'] = avg
                elif player['stat'] == 'pitching':
                    for s in pitching_stat_headers:
                        #print(s)
                        if s in thing['stat']:
                            try:
                                if s == 'balls' or s == 'strikes':
                                    stat_line['B-S'] = '{}-{}'.format(thing['stat']['balls'], thing['stat']['strikes'])
                                else:
                                    stat_line[pitching_stat_headers[s]] = thing['stat'][s]
                            except:
                                stat_line[pitching_stat_headers[s]] = None
                    try:
                        era = '{:.2f}'.format((stat_line['ER']/float(stat_line['IP']))*9)
                    except:
                        if float(stat_line['IP']) == 0.0 and stat_line['ER'] > 0:
                            era = '∞'
                        else:
                            era = '0.00'
                    stat_line['gERA'] = era
                        
        stat_string = ' '.join('{}: {}'.format(self._bold(k),v) for k,v in stat_line.items())
        
        irc.reply('{} ({}) {}'.format(self._bold(self._blue(optplayer.title())), gameDate, stat_string))
        
        return
    
    def _generateStatHeaders(self, called_by):
        
        if called_by == 'mlbstats':
            hitting_stat_headers =                          collections.OrderedDict()
            hitting_stat_headers['gamesPlayed'] =           'GP'
            hitting_stat_headers['atBats'] =                'AB'
            hitting_stat_headers['plateAppearances'] =      'PA'
            hitting_stat_headers['hits'] =                  'H'
            hitting_stat_headers['runs'] =                  'R'
            hitting_stat_headers['doubles'] =               '2B'
            hitting_stat_headers['triples'] =               '3B'
            hitting_stat_headers['homeRuns'] =              'HR'
            hitting_stat_headers['baseOnBalls'] =           'BB'
            hitting_stat_headers['intentionalWalks'] =      'IBB'
            hitting_stat_headers['hitByPitch'] =            'HBP'
            hitting_stat_headers['strikeOuts'] =            'SO'
            hitting_stat_headers['groundOuts'] =            'GO'
            hitting_stat_headers['groundIntoDoublePlay'] =  'GIDP'
            hitting_stat_headers['stolenBases'] =           'SB'
            hitting_stat_headers['caughtStealing'] =        'CS'
            hitting_stat_headers['stolenBasePercentage'] =  'SB%'
            hitting_stat_headers['totalBases'] =            'TB'
            hitting_stat_headers['leftOnBase'] =            'LOB'
            hitting_stat_headers['sacBunts'] =              'sacB'
            hitting_stat_headers['sacFlies'] =              'sacF'
            hitting_stat_headers['babip'] =                 'BABIP'
            hitting_stat_headers['rbi'] =                   'RBI'
            hitting_stat_headers['avg'] =                   'AVG'
            hitting_stat_headers['obp'] =                   'OBP'
            hitting_stat_headers['slg'] =                   'SLG'
            hitting_stat_headers['ops'] =                   'OPS'

            pitching_stat_headers =                         collections.OrderedDict()
            pitching_stat_headers['gamesPlayed'] =          'GP'
            pitching_stat_headers['gamesStarted'] =         'GS'
            pitching_stat_headers['completeGames'] =        'CG'
            pitching_stat_headers['shutouts'] =             'SHO'
            pitching_stat_headers['inningsPitched'] =       'IP'
            pitching_stat_headers['pitchesPerInning'] =     'PitPI'
            pitching_stat_headers['battersFaced'] =         'BF'
            pitching_stat_headers['hits'] =                 'H'
            pitching_stat_headers['baseOnBalls'] =          'BB'
            pitching_stat_headers['intentionalWalks'] =     'IBB'
            pitching_stat_headers['hitBatsmen'] =           'HBP'
            pitching_stat_headers['balks'] =                'BLK'
            pitching_stat_headers['wildPitches'] =          'WP'
            pitching_stat_headers['caughtStealing'] =       'CS'
            pitching_stat_headers['strikeOuts'] =           'K'
            pitching_stat_headers['groundOuts'] =           'GO'
            pitching_stat_headers['earnedRuns'] =           'ER'
            pitching_stat_headers['runs'] =                 'R'
            pitching_stat_headers['homeRuns'] =             'HR'
            pitching_stat_headers['flyOuts'] =              'FO'
            pitching_stat_headers['groundOuts'] =           'GO'
            pitching_stat_headers['era'] =                  'ERA'
            pitching_stat_headers['whip'] =                 'WHIP'
            pitching_stat_headers['avg'] =                  'AVG'
            pitching_stat_headers['obp'] =                  'OBP'
            pitching_stat_headers['slg'] =                  'SLG'
            pitching_stat_headers['ops'] =                  'OPS'
            pitching_stat_headers['strikeoutWalkRatio'] =   'K/W'
            pitching_stat_headers['strikeoutsPer9Inn'] =    'K/9'
            pitching_stat_headers['walksPer9Inn'] =         'W/9'
            pitching_stat_headers['hitsPer9Inn'] =          'H/9'
            pitching_stat_headers['wins'] =                 'W'
            pitching_stat_headers['losses'] =               'L'
            pitching_stat_headers['winPercentage'] =        'W%'
            pitching_stat_headers['saves'] =                'SV'
            pitching_stat_headers['saveOpportunities'] =    'SVO'
            pitching_stat_headers['holds'] =                'HLD'
            
            fielding_stat_headers = None
            
            return hitting_stat_headers, pitching_stat_headers, fielding_stat_headers
        elif called_by == 'fstats':
            fielding_stat_headers =                 collections.OrderedDict()
            fielding_stat_headers['chances'] =      'Chances'
            fielding_stat_headers['errors'] =       'Errors'
            fielding_stat_headers['putOuts'] =      'Put Outs'
            fielding_stat_headers['assists'] =      'Assists'
            fielding_stat_headers['passedBall'] =   'Passed Balls'
            fielding_stat_headers['fielding'] =     'Fielding'
            
            hitting_stat_headers = None
            pitching_stat_headers = None
            
            return hitting_stat_headers, pitching_stat_headers, fielding_stat_headers
        elif called_by == 'mlbgamestats':
            hitting_stat_headers =                      collections.OrderedDict()
            hitting_stat_headers['atBats'] =            'AB'
            hitting_stat_headers['hits'] =              'H'
            hitting_stat_headers['runs'] =              'R'
            hitting_stat_headers['baseOnBalls'] =       'BB'
            hitting_stat_headers['strikeOuts'] =        'SO'
            hitting_stat_headers['doubles'] =           '2B'
            hitting_stat_headers['triples'] =           '3B'
            hitting_stat_headers['homeRuns'] =          'HR'
            hitting_stat_headers['stolenBases'] =       'SB'
            hitting_stat_headers['caughtStealing'] =    'CS'
            hitting_stat_headers['totalBases'] =        'TB'
            hitting_stat_headers['rbi'] =               'RBI'
            hitting_stat_headers['avg'] =               'AVG'

            pitching_stat_headers =                     collections.OrderedDict()
            pitching_stat_headers['inningsPitched'] =   'IP'
            pitching_stat_headers['battersFaced'] =     'BF'
            pitching_stat_headers['hits'] =             'H'
            pitching_stat_headers['baseOnBalls'] =      'BB'
            pitching_stat_headers['strikeOuts'] =       'K'
            pitching_stat_headers['pitchesThrown'] =    '#P'
            pitching_stat_headers['balls'] =            'B-S'
            pitching_stat_headers['strikes'] =          'B-S'
            pitching_stat_headers['hitBatsmen'] =       'HBP'
            pitching_stat_headers['earnedRuns'] =       'ER'
            pitching_stat_headers['runs'] =             'R'
            pitching_stat_headers['homeRuns'] =         'HR'
            pitching_stat_headers['flyOuts'] =          'FO'
            pitching_stat_headers['groundOuts'] =       'GO'
            pitching_stat_headers['era'] =              'gERA'
            
            fielding_stat_headers = None
            
            return hitting_stat_headers, pitching_stat_headers, fielding_stat_headers
        else:
            return None, None, None
            
    @wrap([getopts({'active': '',}), 'text'])
    def mlbroster(self, irc, msg, args, optlist, opttype):
        """<--active> <team> <type>
        Fetches roster for given <team> filtered by <type>"""
        
        optlist = dict(optlist)
        positions = {'pitchers': 'Pitcher', 'infielders': 'Infielder',
                     'catchers': 'Catcher', 'outfielders': 'Outfielder'}
        
        base_url = 'http://statsapi.mlb.com/api/v1/teams/{team}/roster/{roster}'
        api_base = 'http://statsapi.mlb.com'
        
        try:
            team = opttype.split()[0].upper()
        except:
            irc.reply('Invalid input')
            return
        try:
            filter_ = opttype.split()[1]
        except:
            filter_ = None
        #print(filter_)
        try:
            filter_ = filter_.lower()
            filter_ = positions[filter_]
        except:
            if filter_:
                filter_ = filter_.title()
        
        if team not in self._TEAM_BY_TRI:
            irc.reply('ERROR: Invalid team. Valid teams: {}'.format(', '.join(i for i in self._TEAM_BY_TRI)))
            return
        team_id = self._TEAM_BY_TRI[team]
        
        url = base_url.format(team=team_id, roster='active')
        
        data = requests.get(url).json()
        
        #print(data.json())
        roster = []
        tmp = data['roster']
        tmp = sorted(tmp, key=lambda k: k['person']['fullName'].split()[-1])
        #print(tmp)
        for player in tmp:
            num = self._red('#{}'.format(player['jerseyNumber']))
            name = player['person']['fullName']
            info_url = player['person']['link']
            #print(api_base + info_url)
            info = requests.get(api_base + info_url).json()
            bats = info['people'][0]['batSide']['code']
            pits = info['people'][0]['pitchHand']['code']
            string = '{} {} (B:{} T:{})'.format(num, name, bats, pits)
            if filter_:
                if player['position']['type'] == filter_:
                    roster.append(string)
            else:
                roster.append(string)
                
        if not roster:
            irc.reply('Nothing found for that query')
            return
        else:
            irc.reply(', '.join(i for i in roster))
        return
            
    @wrap
    def mlbdaysleft(self, irc, msg, args):
        """How many days are left in the current MLB season"""
        
        now = pendulum.now()
        end = pendulum.parse('201920-09-30')
        left = end-now
        
        irc.reply("There are {} days left in the {} MLB season.".format(left.days, end.year))
            
#     @wrap(['text'])
#     def mlbstats(self, irc, msg, args, player):
#         """<player>
#         Fetches current season stats for the <player> provided.
#         """
        
#         data = batting_stats_bref()
        
#         #print(data.head())
        
            
    @wrap(['text'])
    def lineup2(self, irc, msg, args, team):
        """<team tri code>
        Fetches lineup for the game <team> is playing
        """
        abbv = team.upper()
        #team, date, tz = self._parseInput(team)
        
        team_codes, _ = self._getTeams(league=['1,17', '103,104,119,131,132,133,135,162,516,595'])

        try:
            team, date, tz = inputParser.parseInput(team, team_codes, self._TEAM_BY_NICK)
            print('external parser worked')
        except:
            team, date, tz = self._parseInput(team)
            print('internal parser worked')
        #print(team)
        #print(date)

        
        #print('MLBScores: No cached scores, pulling fresh')
        

        
        if date:
            test = pendulum.parse(date)
            now = pendulum.now().format('YYYY-MM-DD')
            now = pendulum.parse(now)
            k = (test > now)
            #print(date, ' | ', k, ' | ', pendulum.now())
            if k:
                #irc_args = '{} {}'.format(team, date)
                #self.mlb(msg, args, irc_args)
                irc.reply("Sorry I can't predict the future.")
                return

        if not team:
            irc.reply('No team provided.')
            return
        
        games = self._fetchGames(team, date, league=['1,17', '103,104,119,131,132,133,135,162,516,595'])

        #games = self._fetchGames(team, date)

        if not games:
            irc.reply('No games found')
            return

        games = self._parseGames(games, date)
        games = self._sortGames(games)
        
        lineup_url = 'http://statsapi.mlb.com/api/v1/game/{}/boxscore'.format(games[0]['id'])
        lineup_url_2 = 'https://statsapi.mlb.com/api/v1/schedule?gamePk={}&language=en&hydrate=lineups,person,probablePitcher,team(leaders(showOnPreview(leaderCategories=[homeRuns,runsBattedIn,battingAverage],statGroup=[pitching,hitting])))'.format(games[0]['id'])
        print(lineup_url, lineup_url_2)
        
        try:
            data = requests.get(lineup_url).json()
            data2 = requests.get(lineup_url_2).json()
        except:
            irc.reply('Something went wrong fetching game data.')
            return
        #print(team)
        lineup = []
        tmp_plyr_data = []
        opp_id = None
        #try:
        teams = data['teams']
        lineups = data2['dates'][0]['games'][0]['lineups']
        #print(lineups)
        ppitchers = data2['dates'][0]['games'][0]['teams']
        for item in teams:
            if int(team) == teams[item]['team']['id']:
                #print('h/a: ', item)
                if item == 'home':
                    opp_t = 'away'
                    hora = item
                elif item == 'away':
                    opp_t = 'home'
                    hora = item
                #print('pitcher: ', opp_t)
                battingOrder = teams[item]['battingOrder']
                tmp_plyr_data = teams[item]['players']
                vs_name = teams[opp_t]['team']['abbreviation']
                
                #pprint(teams[opp_t])
                if teams[opp_t]['pitchers']:
                    opp_id = teams[opp_t]['pitchers'][-1]
                    hm_id = teams[item]['pitchers'][-1]
                    #print('teams')
                else:
                    opp_id = ppitchers[opp_t]['probablePitcher']['id']
                    hm_id = ppitchers[item]['probablePitcher']['id']
                    #print('ppitchers')
                break
        #print(tmp_plyr_data)
        if lineups:
            #print('Got a lineup')
            tstr = '{}Players'.format(hora)
            #print(lineups)
            try:
                lineups = lineups[tstr]
            except:
                irc.reply('No lineup found')
                return
            for idx, player in enumerate(lineups):
                if battingOrder:
                    if int(player['id']) != int(battingOrder[idx]):
                        player['id'] = int(battingOrder[idx])
                #print(idx, player)
                plyr_url = 'http://statsapi.mlb.com/api/v1/people/{}'.format(player['id'])
                #print(plyr_url)
                n_player_data = requests.get(plyr_url).json()
                for pid in tmp_plyr_data:
                    if str(player['id']) in str(pid):
                        player_data = tmp_plyr_data[pid]
                bats = n_player_data['people'][0]['batSide']['code']
                name = player_data['person']['fullName']
                try:
                    post = lineups[idx]['primaryPosition']['abbreviation']
                except:
                    post = player_data['position']['abbreviation']
                if idx == 9:
                    bats = n_player_data['people'][0]['pitchHand']['code']
                    tmp = '\x02\x0312{}\x03\x02 {} ({})'.format('P', name, bats)
                else:
                    tmp = '\x02\x0312{}\x03\x02 {} ({}) {}'.format(idx+1, name, bats, post)
                lineup.append(tmp)
       
            #umps = item['value']
            if opp_id:
                pitcher_url = 'http://statsapi.mlb.com/api/v1/people/{}'.format(opp_id)
                #print(pitcher_url)
                pitcher_data = requests.get(pitcher_url).json()
                pitch_name = pitcher_data['people'][0]['fullName']
                pitches = pitcher_data['people'][0]['pitchHand']['code']
                for pplayer in data['teams'][opp_t]['players']:
                    if str(opp_id) in pplayer:
                        era = data['teams'][opp_t]['players'][pplayer]['seasonStats']['pitching']['era']
                pitcher = '{} ({}) {}'.format(pitch_name, pitches, era)
            else:
                pitcher = ''
                
            if hm_id and len(lineup) == 9:
                pitcher_url = 'http://statsapi.mlb.com/api/v1/people/{}'.format(hm_id)
                #print(pitcher_url)
                pitcher_data = requests.get(pitcher_url).json()
                pitch_name = pitcher_data['people'][0]['fullName']
                pitches = pitcher_data['people'][0]['pitchHand']['code']
                for pplayer in data['teams'][hora]['players']:
                    if str(hm_id) in pplayer:
                        era = data['teams'][hora]['players'][pplayer]['seasonStats']['pitching']['era']
                hm_pitcher = ' :: \x02\x0312{}\x03\x02 {} ({}) {}'.format('P', pitch_name, pitches, era)
            else:
                hm_pitcher = ''
#         except:
#             irc.reply('Something went wrong parsing game data.')
#             return
        
        if not lineup:
            irc.reply('No lineup found yet, game active?')
            return
        
        irc.reply('{} Lineup vs {} - \x02{}\x02 :: {}{}'.format(abbv, vs_name, pitcher, ', '.join(plr for plr in lineup), hm_pitcher))
        
            
    @wrap(['text'])
    def umps(self, irc, msg, args, team):
        """<team tri code>
        Fetches umpires for the game <team> is playing
        """
        team, date, tz = self._parseInput(team)
        
        if date:
            test = pendulum.parse(date)
            now = pendulum.now().format('YYYY-MM-DD')
            now = pendulum.parse(now)
            k = (test > now)
            #print(date, ' | ', k, ' | ', pendulum.now())
            if k:
                #irc_args = '{} {}'.format(team, date)
                #self.mlb(msg, args, irc_args)
                irc.reply("Sorry I can't predict the future.")
                return

        if not team:
            irc.reply('No team provided.')
            return

        games = self._fetchGames(team, date)

        if not games:
            irc.reply('No games found')
            return

        games = self._parseGames(games, date)
        games = self._sortGames(games)
        
        ump_url = 'http://statsapi.mlb.com/api/v1/game/{}/boxscore'.format(games[0]['id'])
        #print(ump_url)
        
        try:
            data = requests.get(ump_url).json()
        except:
            irc.reply('Something went wrong fetching game data.')
            return
        
        umps = None
        try:
            for item in data['info']:
                if item['label'] == 'Umpires':
                    umps = item['value']
                    break
        except:
            irc.reply('Something went wrong parsing game data.')
            return
        
        if not umps:
            irc.reply('No umpires found yet, game active?')
            return
        
        irc.reply('Umpires: {}'.format(umps))
        

    @wrap([optional('text')])
    def mlbpitcher(self, irc, msg, args, irc_args=None):
        """<team tri code> [<date>]
        Fetches pitcher(s) for given team and/or date. Defaults to today
        if no input provided"""

        override = False
        starter_only = False
        if irc_args:
            if '--all' in irc_args:
                override = True
                irc_args = irc_args.replace('--all', '')
            if 'was' in irc_args:
                irc_args = irc_args.replace('was', 'wsh')
            if '--starter' in irc_args:
                starter_only = True
                override = True
                irc_args = irc_args.replace('--starter', '')
                

        team, date, tz = self._parseInput(irc_args)
        
        if date:
            test = pendulum.parse(date)
            now = pendulum.now().format('YYYY-MM-DD')
            now = pendulum.parse(now)
            k = (test > now)
            #print(date, ' | ', k, ' | ', pendulum.now())
            if k:
                #irc_args = '{} {}'.format(team, date)
                #self.mlb(msg, args, irc_args)
                irc.reply("Sorry I can't predict the future.")
                return

        if not team:
            irc.reply('No team provided.')
            return

        games = self._fetchGames(team, date)

        if not games:
            irc.reply('No games found')
            return

        games = self._parseGames(games, date)
        games = self._sortGames(games)

        pitchers = self._fetchPitchers(games, team, override)

        if not pitchers:
            irc.reply('No pitchers found, has game started yet?')
            return
        
        #print(pitchers)

        # if len(pitchers) == 2:
        #     if 'Game 2' in pitchers[1]:
        #         irc.reply('No pitchers found, has game started yet?')
        #         return

        reply_string = self._replyPitchersAsString(pitchers)

        # if len(reply_string) > 3:
        #     print(reply_string)
        #     if 'Game 2' in reply_string[-1]:
        #         reply_string.append('Not started yet')

        # what = type(reply_string)
        # print(what)

        #print(reply_string)

        if type(reply_string) is tuple or type(reply_string) is list or type(reply_string) is dict:
            if type(reply_string) is dict:
                for string in reply_string:
                    irc.reply('\x02{}\x02'.format(string))
                    if starter_only:
                        irc.reply(reply_string[string][0])
                    else:
                        for pit in reply_string[string]:
                            irc.reply(pit)
            else:
                if starter_only:
                    irc.reply(reply_string[0])
                else:
                    for string in reply_string:
                        irc.reply(string)
        else:
            irc.reply(reply_string)
            
    @wrap(['text'])
    def mlbinjuries(self, irc, msg, args, optteam):
        """<team>
        Returns injuries for given <team>.
        """
        
        # get team id for matching
        team, _, _ = self._parseInput(optteam)
        
        # url to get data
        url = 'http://mlb.mlb.com/fantasylookup/json/named.wsfb_news_injury.bam'
        
        # try to get the data
        try:
            data = requests.get(url).json()
        except:
            irc.reply('Something went wrong fetching the data.')
            return
        
        # pull out the relevant data
        injuries = data['wsfb_news_injury']['queryResults']['row']
        
        # build output
        output = []
        
        for injury in injuries:
            #print(team, int(injury['team_id']))
            if not team:
                if optteam.lower() in '{} {}'.format(injury['name_first'].lower(), injury['name_last'].lower()):
                    name = '\x02\x0312{} {}\x03\x02 ({})'.format(injury['name_first'],
                                                                 injury['name_last'],
                                                                 injury['position'])
                    inj = '{} on {} ({})'.format(injury['injury_status'],
                                                 injury['insert_ts'],
                                                 injury['injury_desc'])
                    upd = '\x02Latest:\x02 {}'.format(injury['injury_update'])
                    due = '\x02Returning:\x02 {}'.format(injury['due_back'])
                    output.append('{} :: {} | {} | {}'.format(name, inj, upd, due))
            else:
                if int(team) == int(injury['team_id']):
                    # our team query matches let's go
                    name = '\x02\x0312{} {}\x03\x02 ({})'.format(injury['name_first'],
                                               injury['name_last'],
                                               injury['position'])
                    inj = '{} on {}'.format(injury['injury_status'],
                                            injury['insert_ts'])
                    output.append('{} {}'.format(name, inj))
                
        if not output:
            irc.reply('ERROR: Team or player not found or no injuries found for provided team or player.')
            return
                
        if team:
            team_name = '\x02{}:\x02 '.format(self._TEAM_BY_ID['{}'.format(team)])
            irc.reply('{}{}'.format(team_name, ', '.join(i for i in output)))
        else:
            irc.reply(' || '.join(i for i in output))
            
    @wrap([optional('int'), 'somethingwithoutspaces', optional('somethingwithoutspaces')])
    def next(self, irc, msg, args, optdays, optteam, optteam2):
        """[<#>] <team> [<team>]
        Returns the next # of games for team (or team vs team), defaults to 1 if not given
        """
        
        tids = self._TEAM_BY_TRI
        
        if not optdays:
            optdays = 1
            
        if optdays == 0:
            optdays = 1
            
        if optdays < 0:
            optdays = optdays * -1
            
        if optdays > 10:
            irc.reply('ERROR: Too many games, has to be less than 10')
            return
            
        
        optteam = optteam.upper()
        
        if optteam not in tids:
            irc.reply('ERROR: Invalid team, must be team abbreviation (ex: BOS)')
            return
        
        if optteam2:
            optteam2 = optteam2.upper()
            if optteam == optteam2:
                irc.reply('ERROR: Both provided teams are the same')
                return
            if optteam2 not in tids:
                irc.reply('ERROR: Invalid team, must be team abbreviation (ex: BOS)')
                return
        
        today = self._getTodayDate()
        end = '2019-11-01'
        try:
            tid = tids[optteam]
        except:
            irc.reply('ERROR: Something went wrong parsing data')
            return
        #print(optdays, optteam)
        # TBD switch out season=YYYYYYYY automatically
        if optteam2:
            try:
                tid2 = tids[optteam2]
            except:
                irc.reply('ERROR: Something went wrong parsing data')
                return
            # url = ("https://statsapi.web.nhl.com/api/v1/schedule?startDate={}&endDate={}" +
            #       "&expand=schedule.teams,schedule.linescore,schedule.broadcasts.all,schedule.ticket,schedule.game.content.media.epg" +
            #       "&leaderCategories=&site=en_nhl&teamId={}&teamId={}")
            url = ('https://statsapi.mlb.com/api/v1/schedule'
                                     '?sportId=1&startDate={}&endDate={}'
                                     '&hydrate=linescore,team,probablePitcher'
                                     '&teamId={}&teamId={}')

            # Fetch content
            content = requests.get(url.format(today, end, tid, tid2))
            content_json = content.json()
            #print(url.format(today, end, tid))
        else:
            url = ('https://statsapi.mlb.com/api/v1/schedule'
                                     '?sportId=1&startDate={}&endDate={}'
                                     '&hydrate=linescore,team,probablePitcher'
                                     '&teamId={}')

            # Fetch content
            content = requests.get(url.format(today, end, tid))
            content_json = content.json()
            #print(url.format(today, end, tid))
        
        games = []
        
        if optteam2:
            for idx, item in enumerate(content_json['dates']):
                for gidx, _ in enumerate(item['games']):
                    if optteam in item['games'][gidx]['teams']['away']['team']['abbreviation'] and optteam2 in item['games'][gidx]['teams']['home']['team']['abbreviation']:
                        string1 = '{}'.format(self._ISODateToEasternTimeNext(item['games'][gidx]['gameDate']))
                        string2 = '{} @ {}'.format(self._bold(item['games'][gidx]['teams']['away']['team']['abbreviation']), item['games'][gidx]['teams']['home']['team']['abbreviation'])
                        ppitchers = ''
                        if 'probablePitcher' in item['games'][gidx]['teams']['away'] and 'probablePitcher' in item['games'][gidx]['teams']['home']:
                            ppitchers = ' - {} vs {}'.format(item['games'][gidx]['teams']['away']['probablePitcher']['fullName'].split(',')[0], item['games'][gidx]['teams']['home']['probablePitcher']['fullName'].split(',')[0])
                        games.append(string1 + ' | ' + string2 + ppitchers)
                    elif optteam2 in item['games'][gidx]['teams']['away']['team']['abbreviation'] and optteam in item['games'][gidx]['teams']['home']['team']['abbreviation']:
                        string1 = '{}'.format(self._ISODateToEasternTimeNext(item['games'][gidx]['gameDate']))
                        string2 = '{} @ {}'.format(item['games'][gidx]['teams']['away']['team']['abbreviation'], self._bold(item['games'][gidx]['teams']['home']['team']['abbreviation']))
                        ppitchers = ''
                        if 'probablePitcher' in item['games'][gidx]['teams']['away'] and 'probablePitcher' in item['games'][gidx]['teams']['home']:
                            ppitchers = ' - {} vs {}'.format(item['games'][gidx]['teams']['away']['probablePitcher']['fullName'].split(',')[0], item['games'][gidx]['teams']['home']['probablePitcher']['fullName'].split(',')[0])
                        games.append(string1 + ' | ' + string2 + ppitchers)
                        
                    else:
                        pass
            
            if len(games) == 0:
                irc.reply('No future games found for {} vs {}'.format(optteam, optteam2))
                return
            #print(games)
            games = games[:optdays]
            
            if len(games) <= 4:
                for game in games:
                    irc.sendMsg(ircmsgs.privmsg(msg.args[0], game))
            else:
                #m = len(games)
                for game in games[:4]:
                    irc.sendMsg(ircmsgs.privmsg(msg.args[0], game))
                for game in games[4:]:
                    irc.reply(game)
        else:
            for idx, item in enumerate(content_json['dates'][:optdays]):
                for gidx, _ in enumerate(item['games']):
                    #print(item['games'][gidx]['teams']['away']['team']['id'])
                    string1 = '{}'.format(self._ISODateToEasternTimeNext(item['games'][gidx]['gameDate']))
                    necessary = ''
                    if item['games'][gidx]['ifNecessary'] == 'Y':
                        necessary = ' - If Necessary'
                    #string2 = '{}'.format('{} {}'.format('at', item['games'][gidx]['teams']['home']['team']['abbreviation']) if int(tid) == item['games'][gidx]['teams']['away']['team']['id'] else '{} {}'.format('vs', item['games'][gidx]['teams']['away']['team']['abbreviation']))
                    if optteam in item['games'][gidx]['teams']['away']['team']['abbreviation']:
                        string2 = '{} @ {}'.format(self._bold(item['games'][gidx]['teams']['away']['team']['abbreviation']), item['games'][gidx]['teams']['home']['team']['abbreviation'])
                    else:
                        string2 = '{} @ {}'.format(item['games'][gidx]['teams']['away']['team']['abbreviation'], self._bold(item['games'][gidx]['teams']['home']['team']['abbreviation']))
                    ppitchers = ''
                    if 'probablePitcher' in item['games'][gidx]['teams']['away'] and 'probablePitcher' in item['games'][gidx]['teams']['home']:
                        ppitchers = ' - {} vs {}'.format(item['games'][gidx]['teams']['away']['probablePitcher']['fullName'].split(',')[0], item['games'][gidx]['teams']['home']['probablePitcher']['fullName'].split(',')[0])
                    games.append(string1 + ' | ' + string2 + ppitchers + necessary)
            if len(games) <= 4:
                for game in games:
                    irc.sendMsg(ircmsgs.privmsg(msg.args[0], game))
            else:
                #m = len(games)
                for game in games[:4]:
                    irc.sendMsg(ircmsgs.privmsg(msg.args[0], game))
                for game in games[4:]:
                    irc.reply(game)


    @wrap([optional('int'), 'somethingwithoutspaces', optional('somethingwithoutspaces')])
    def last(self, irc, msg, args, optdays, optteam, optteam2):
        """[<#>] <team> [<team>]
        Returns the last # of games for team (or team vs team), defaults to 1 if not given
        """
        
        tids = self._TEAM_BY_TRI
        
        if not optdays:
            optdays = -1
            numdays = 1
        else:
            if optdays > 10:
                irc.reply('ERROR: Too many games, has to be less than 10')
                return
            if optdays == 0:
                optdays = 1
            if optdays < 0:
                optdays = optdays * -1
            if optdays > 10:
                irc.reply('ERROR: Too many games, has to be less than 10')
                return
            numdays = optdays
            optdays = optdays * -1
            
        optteam = optteam.upper()
        
        if optteam not in tids:
            irc.reply('ERROR: Invalid team, must be team abbreviation (ex: BOS)')
            return
        
        if optteam2:
            optteam2 = optteam2.upper()
            if optteam == optteam2:
                irc.reply('ERROR: Both provided teams are the same')
                return
            if optteam2 not in tids:
                irc.reply('ERROR: Invalid team, must be team abbreviation (ex: BOS)')
                return
        
        today = self._getTodayDate()
        dt_today = datetime.datetime.strptime(today, "%Y-%m-%d")
        dt_yesterday = dt_today - datetime.timedelta(1)
        yesterday = dt_yesterday.strftime('%Y-%m-%d')
        #last_date = datetime.datetime.today() - datetime.timedelta(days=optdays)
        #print(last_date)
        end = '2019-03-01'
        try:
            tid = tids[optteam]
        except:
            irc.reply('ERROR: Something went wrong parsing data')
            return
        #print(optdays, optteam)
        # TBD switch out season=YYYYYYYY automatically
        if optteam2:
            try:
                tid2 = tids[optteam2]
            except:
                irc.reply('ERROR: Something went wrong parsing data')
                return
            url = ('https://statsapi.mlb.com/api/v1/schedule'
                                     '?sportId=1&startDate={}&endDate={}'
                                     '&hydrate=linescore,team,decisions'
                                     '&teamId={}&teamId={}')

            # Fetch content
            content = requests.get(url.format(end, yesterday, tid, tid2))
            content_json = content.json()
            
            #print(url.format(today, end, tid, tid2))
        else:
            url = ('https://statsapi.mlb.com/api/v1/schedule'
                                     '?sportId=1&startDate={}&endDate={}'
                                     '&hydrate=linescore,team,decisions'
                                     '&teamId={}')

            # Fetch content
            content = requests.get(url.format(end, yesterday, tid))
            content_json = content.json()
            #print(url.format(end, yesterday, tid))

        games = []

        if optteam2: # team vs team
            for idx, item in enumerate(content_json['dates']):
                for gidx, _ in enumerate(item['games']):
                    if (optteam in item['games'][gidx]['teams']['away']['team']['abbreviation'] and optteam2 in item['games'][gidx]['teams']['home']['team']['abbreviation']) or (optteam2 in item['games'][gidx]['teams']['away']['team']['abbreviation'] and optteam in item['games'][gidx]['teams']['home']['team']['abbreviation']):
                        date = self._ISODateToEasternTimeNext(item['games'][gidx]['gameDate'])[:-3]

                        status_codes = ['DI', 'DC', 'DR', 'DS', 'PI']
                        #print(item['games'][gidx]['status']['statusCode'])
                        if item['games'][gidx]['status']['statusCode'] in status_codes:
                            #print('hi ppd')
                            home = item['games'][gidx]['teams']['home']['team']['abbreviation']
                            away = item['games'][gidx]['teams']['away']['team']['abbreviation']
                            #ppd = ' \x037P\x03'
                            ppd = '  '
                            reason = item['games'][gidx]['status']['reason']
                            str_reply = '{} @ {} \x034PPD\x03 ({})'.format(away, home, reason)
                            string1 = '{}'.format(date.split(',')[0])
                            games.append(string1 + ppd + ' | ' + str_reply)
                            continue

                        if int(item['games'][gidx]['linescore']['currentInning']) > 9:
                            ot_type = ' (' + item['games'][gidx]['linescore']['currentInningOrdinal'] + ')'
                        else:
                            ot_type = ''

                        string1 = '{}'.format(date.split(',')[0])

                        if int(item['games'][gidx]['teams']['away']['score']) > int(item['games'][gidx]['teams']['home']['score']):
                            away = self._bold(item['games'][gidx]['teams']['away']['team']['abbreviation'])
                            away_s = self._bold(item['games'][gidx]['teams']['away']['score'])
                            home = item['games'][gidx]['teams']['home']['team']['abbreviation']
                            home_s = item['games'][gidx]['teams']['home']['score']
                            if optteam in away:
                                result = self._green(' W')
                                try:
                                    pitcher = ' - {}'.format(item['games'][gidx]['decisions']['winner']['fullName'])
                                except:
                                    pitcher = ''
                            else:
                                result = self._red(' L')
                                try:
                                    pitcher = ' - {}'.format(item['games'][gidx]['decisions']['loser']['fullName'])
                                except:
                                    pitcher = ''
                        else:
                            home = self._bold(item['games'][gidx]['teams']['home']['team']['abbreviation'])
                            home_s = self._bold(item['games'][gidx]['teams']['home']['score'])
                            away = item['games'][gidx]['teams']['away']['team']['abbreviation']
                            away_s = item['games'][gidx]['teams']['away']['score']
                            if optteam in home:
                                result = self._green(' W')
                                try:
                                    pitcher = ' - {}'.format(item['games'][gidx]['decisions']['winner']['fullName'])
                                except:
                                    pitcher = ''
                            else:
                                result = self._red(' L')
                                try:
                                    pitcher = ' - {}'.format(item['games'][gidx]['decisions']['loser']['fullName'])
                                except:
                                    pitcher = ''

                        string3 = '{} {} @ {} {}{}{}'.format(away, away_s, home, home_s, ot_type, pitcher)

                        games.append(string1 + result + ' | ' + string3)
                    else:
                        pass

            #games = games[::-1]
            games_r = games[optdays:]
            games_r.reverse()
            
            if len(games) <= 4:
                for game in games_r:
                    irc.sendMsg(ircmsgs.privmsg(msg.args[0], game))
            else:
                for game in games_r[:4]:
                    irc.sendMsg(ircmsgs.privmsg(msg.args[0], game))
                for game in games_r[4:]:
                    irc.reply(game)
                
        else: # just team
            for idx, item in enumerate(content_json['dates'][optdays:]):
                for gidx, _ in enumerate(item['games']):
                    date = self._ISODateToEasternTimeNext(item['games'][gidx]['gameDate'])#[:-3]

                    status_codes = ['DI', 'DC', 'DR', 'DS']
                    #print(item['games'][gidx]['status']['statusCode'])
                    if item['games'][gidx]['status']['statusCode'] in status_codes:
                        #print('hi ppd')
                        home = item['games'][gidx]['teams']['home']['team']['abbreviation']
                        away = item['games'][gidx]['teams']['away']['team']['abbreviation']
                        #ppd = ' \x037P\x03'
                        ppd = '  '
                        reason = item['games'][gidx]['status']['reason']
                        str_reply = '{} @ {} \x034PPD\x03 ({})'.format(away, home, reason)
                        string1 = '{}'.format(date.split(',')[0])
                        games.append(string1 + ppd + ' | ' + str_reply)
                        continue

                    if int(item['games'][gidx]['linescore']['currentInning']) > 9:
                        ot_type = ' (F/' + item['games'][gidx]['linescore']['currentInningOrdinal'] + ')'
                    else:
                        ot_type = ''

                    string1 = '{}'.format(date.split(',')[0])

                    if int(item['games'][gidx]['teams']['away']['score']) > int(item['games'][gidx]['teams']['home']['score']):
                        away = self._bold(item['games'][gidx]['teams']['away']['team']['abbreviation'])
                        away_s = self._bold(item['games'][gidx]['teams']['away']['score'])
                        home = item['games'][gidx]['teams']['home']['team']['abbreviation']
                        home_s = item['games'][gidx]['teams']['home']['score']
                        if optteam in away:
                            result = self._green(' W')
                            try:
                                pitcher = ' - {}'.format(item['games'][gidx]['decisions']['winner']['fullName'])
                            except:
                                pitcher = ''
                        else:
                            result = self._red(' L')
                            try:
                                pitcher = ' - {}'.format(item['games'][gidx]['decisions']['loser']['fullName'])
                            except:
                                pitcher = ''
                    else:
                        home = self._bold(item['games'][gidx]['teams']['home']['team']['abbreviation'])
                        home_s = self._bold(item['games'][gidx]['teams']['home']['score'])
                        away = item['games'][gidx]['teams']['away']['team']['abbreviation']
                        away_s = item['games'][gidx]['teams']['away']['score']
                        if optteam in home:
                            result = self._green(' W')
                            try:
                                pitcher = ' - {}'.format(item['games'][gidx]['decisions']['winner']['fullName'])
                            except:
                                pitcher = ''
                        else:
                            result = self._red(' L')
                            try:
                                pitcher = ' - {}'.format(item['games'][gidx]['decisions']['loser']['fullName'])
                            except:
                                pitcher = ''

                    string3 = '{} {} @ {} {}{}{}'.format(away, away_s, home, home_s, ot_type, pitcher)

                    games.append(string1 + result + ' | ' + string3)
            
            games_r = games[::-1]
            
            if len(games) <= 4:
                for game in games_r:
                    irc.sendMsg(ircmsgs.privmsg(msg.args[0], game))
            else:
                for game in games_r[:4]:
                    irc.sendMsg(ircmsgs.privmsg(msg.args[0], game))
                for game in games_r[4:]:
                    irc.reply(game)
                    
#     @wrap(["text"])
#     def recap(self, irc, msg, args, optargs):
#         """<team> [<date>]
#         Returns a video recap from <team> optionally on <date>.
#         """
        
#         # hq = False
#         # if '--hq' in optargs or '--HQ' in optargs:
#         #     hq = True
#         #     optargs = optargs.strip('--hq')
#         #     optargs = optargs.strip('--HQ')
#         #     optargs = optargs.strip()
            
#         # print(optargs)
        
#         tids = self._TEAM_BY_TRI
        
# #         try:
# #             gamepk = self._findGamepk("summary", optargs)
# #         except:
# #             # try looking for yesterday's game
# #             #optargs += ' yesterday'
            
# #         try:
#         api_url = 'https://statsapi.mlb.com/api/v1/teams/{}/?expand=team.schedule.previous'.format(tids[optargs.upper()])
#         print(api_url)
#         data = requests.get(api_url)
#         data = data.json()
#         gamepk = str(data['teams'][0]['previousGameSchedule']['dates'][0]['games'][gidx]['gamePk'])
# #         except:
# #             irc.reply('Nothing found for given input')
# #             return

#         if not gamepk:
#             irc.reply('Nothing found, check your input')
#             return
#         url = ("http://statsapi.mlb.com/api/v1/schedule?expand=schedule.game.content.media.epg&leaderCategories=&site=en_nhl&gamePk=" + gamepk)
#         content = requests.get(url)
#         content_json = content.json()

#         print(url)
                
#         info = {}
#         #print(gamepk)
        
#         VIDEOurl = {}
#         try:
#             for item in content_json['dates'][0]['games'][gidx]['content']['media']['epg']:
#                 if item['title'] == 'Recap':
#                     info['title'] = item['items'][0]['title'].strip('Recap: ')
#                     info['blurb'] = item['items'][0]['blurb']
#                     info['description'] = item['items'][0]['description']
#                     info['duration'] = "{}m{}s".format(item['items'][0]['duration'].split(':')[0].lstrip('0'), item['items'][0]['duration'].split(':')[1])
#                     for video in item['items'][0]['playbacks']:
#                         if 'HTTP_CLOUD_WIRED_60' in video['name']:
#                             VIDEOurl['hls'] = self._shortenUrl(video['url'])
#                         if '1800K' in video['name']:
#                             VIDEOurl['mp4'] = self._shortenUrl(video['url'])
#             # if not VIDEOurl:
#             #     VIDEOurl = 'No video recap available'
#             # else:
#             #     VIDEOurl = self._shortenUrl(VIDEOurl)
#             # info['url'] = VIDEOurl
#         except:
#             VIDEOurl = 'No video recap available'
            
#         if not VIDEOurl:
#             VIDEOurl = 'No video recap available'
        
#         #test = {}
#         #test['url'] = 'hi this is a test'
        
#         #print(len(test))
        
#         if len(info) <= 1:
#             irc.reply('No video recap available.')
#             return
        
#         reply_string = ["\x02{}\x02 :: {}".format(info['title'],
#                                                   info['blurb']),
#                         "{}".format(info['description']),
#                         "\x02MP4:\x02 {} | \x02HLS:\x02 {} | {}".format(VIDEOurl['mp4'], VIDEOurl['hls'], info['duration'])]
        
#         for item in reply_string:
#             irc.sendMsg(ircmsgs.privmsg(msg.args[0], item))
                    
    def _red(self, string):
        """Returns a red string."""
        return ircutils.mircColor(string, 'red')

    def _yellow(self, string):
        """Returns a yellow string."""
        return ircutils.mircColor(string, 'yellow')

    def _green(self, string):
        """Returns a green string."""
        return ircutils.mircColor(string, 'green')

    def _blue(self, string):
        """Returns a blue string."""
        return ircutils.mircColor(string, 'blue')

    def _bold(self, string):
        """Returns a bold string."""
        return ircutils.bold(string)

    def _ul(self, string):
        """Returns an underline string."""
        return ircutils.underline(string)

    def _bu(self, string):
        """Returns a bold/underline string."""
        return ircutils.bold(ircutils.underline(string))

############################
# Date-manipulation helpers
############################
    def _getTodayDate(self):
        """Get the current date formatted as "YYYYMMDD".
        Because the API separates games by day of start, we will consider and
        return the date in the Pacific timezone.
        The objective is to avoid reading future games anticipatedly when the
        day rolls over at midnight, which would cause us to ignore games
        in progress that may have started on the previous day.
        Taking the west coast time guarantees that the day will advance only
        when the whole continental US is already on that day."""
        today = self._pacificTimeNow().date()
        today_iso = today.isoformat()
        return today_iso #.replace('-', '')

    def _easternTimeNow(self):
        return datetime.datetime.now(pytz.timezone('US/Eastern'))

    def _pacificTimeNow(self):
        return datetime.datetime.now(pytz.timezone('US/Pacific'))
    
    def _ISODateToEasternTimeNext(self, iso):
        """Convert the ISO date in UTC time that the API outputs into an
        Eastern time formatted with am/pm. (The default human-readable format
        for the listing of games)."""
        date = dateutil.parser.parse(iso)
        date_eastern = date.astimezone(pytz.timezone('US/Eastern'))
        eastern_time = date_eastern.strftime('%a %m/%d, %I:%M %p %Z')
        return "{}".format(eastern_time) # Strip the seconds

    def _fetchPitchers(self, games, team, override):
        """fetch pitchers"""

        data = {}
        current_only = False
        ss_dh = False
        test_status = 'I'
        #print(games)
        for idx, game in enumerate(games):
            data['Game {}'.format(idx+1)] = []
            # if len(games) > 1:
            #     ss_dh = True
            #     data.append('\x02Game {}\x02'.format(idx+1))
            gpk = game['id']
            #print(game['status'])
            if 'I' in game['status']:
                current_only = True if not override else False
            if 'S' == game['status']:
                data['Game {}'.format(idx+1)] = False
                break
            url = 'https://statsapi.mlb.com/api/v1/game/{}/boxscore'.format(gpk)
            #print(url)
            temp = requests.get(url).json()
            for teams in temp['teams']:
                #print(temp['teams'][teams]['team']['id'])
                if int(team) == temp['teams'][teams]['team']['id']:
                    pitcher_ids = temp['teams'][teams]['pitchers']
                    for pitcher_id in pitcher_ids:
                        for player in temp['teams'][teams]['players']:
                            if int(pitcher_id) == temp['teams'][teams]['players'][player]['person']['id']:
                                if current_only:
                                    #if temp['teams'][teams]['players'][player]['gameStatus']['isCurrentPitcher']:
                                    data['Game {}'.format(idx+1)] = [temp['teams'][teams]['players'][player]]
                                else:
                                    data['Game {}'.format(idx+1)].append(temp['teams'][teams]['players'][player])
            #print(data)

        #print(data)
        #print(current_only, data)
        if current_only and not data:
            return ['No current pitcher for {} (use --all to see every pitcher)'.format(self._TEAM_BY_ID[team])]
        
        if not data:
            return None

        if len(data) > 1:
            for d in data:
                if not data[d]:
                    data[d] = ['No current pitcher for {} in {} (use --all to see every pitcher)'.format(self._TEAM_BY_ID[team], d)]
        else:
            for d in data:
                if not data[d]:
                    data[d] = ['No current pitcher for {} (use --all to see every pitcher)'.format(self._TEAM_BY_ID[team])]

        return data

    def _replyPitchersAsString(self, pitchers):
        """parses and returns pitchers"""

        resp = []
        width = 0

        def _iteratePitchers(pitchers):

            resp = []
            width = 0

            #print(pitchers)
            for idx, pitcher in enumerate(pitchers):
                #print(pitcher)
                if type(pitcher) == str:
                    continue
                name = pitcher['person']['fullName']
                name = ' '.join(name.split())
                suffixes = ['jr.']
                lname = -1
                for suffix in suffixes:
                    if name.split(' ')[lname].lower() in suffix:
                        lname = -2
                    else:
                        lname = -1
                if len(name.split(' ')[lname]) > width:
                    width = len(name.split(' ')[lname])

            for pitcher in pitchers:
                if type(pitcher) == str:
                    resp.append(pitcher)
                    continue
                name = pitcher['person']['fullName']
                name = ' '.join(name.split())
                stats = pitcher['stats']['pitching']
                try:
                    era = '{:.2f}'.format((stats['earnedRuns']/float(stats['inningsPitched']))*9)
                except:
                    if float(stats['inningsPitched']) == 0.0 and stats['earnedRuns'] > 0:
                        era = '∞'
                    else:
                        era = '0.00'
                try:
                    opBA = '{:.3f}'.format((stats['hits'])/(stats['battersFaced'] - stats['baseOnBalls']))
                except:
                    opBA = '.000'
                
                suffixes = ['jr.']
                lname = -1
                #print(name.split(' ')[lname].lower())
                for suffix in suffixes:
                    #print(suffix)
                    if name.split(' ')[lname].lower() in suffix:
                        #print('hi')
                        lname = -2
                    else:
                        lname = -1
                string = ('\x02\x0312{}. {:{width}}\x03 IP:\x02 {} '
                                        '\x02H:\x02 {} '
                                        '\x02R:\x02 {} '
                                        '\x02ER:\x02 {} '
                                        '\x02BB:\x02 {} '
                                        '\x02K:\x02 {} '
                                        '\x02HR:\x02 {} '
                                        '\x02BF:\x02 {:>2} '
                                        '\x02Pit:\x02 {:>3} '
                                        '\x02B-S:\x02 {:>2}-{:<2} '
                                        '\x02ERA:\x02 {:>6} '
                                        '\x02OpBA:\x02 {}').format(
                    name[0],
                    name.split(' ')[lname],
                    '0' if not stats.get('inningsPitched') else stats.get('inningsPitched'),
                    '0' if not stats.get('hits') else stats.get('hits'),
                    '0' if not stats.get('runs') else stats.get('runs'),
                    '0' if not stats.get('earnedRuns') else stats.get('earnedRuns'),
                    '0' if not stats.get('baseOnBalls') else stats.get('baseOnBalls'),
                    '0' if not stats.get('strikeOuts') else stats.get('strikeOuts'),
                    '0' if not stats.get('homeRuns') else stats.get('homeRuns'),
                    '0' if not stats.get('battersFaced') else stats.get('battersFaced'),
                    '0' if not stats.get('pitchesThrown') else stats.get('pitchesThrown'),
                    '0' if not stats.get('balls') else stats.get('balls'),
                    '0' if not stats.get('strikes') else stats.get('strikes'),
                    era,
                    opBA,
                    width=str(width))
                resp.append(string)
            return resp

        
        #print(len(pitchers))

        if len(pitchers) > 1:
            # double header
            #print('hi')
            resp = {}
            for game in pitchers:
                #print(pitchers[game])
                if "No current pitcher" not in pitchers[game][0]:
                    resp[game] = _iteratePitchers(pitchers[game])
        else:
            g1_pitchers = pitchers['Game 1']
            resp = _iteratePitchers(g1_pitchers)

        #print(resp)
        
        return resp

    def _sortGames(self, games):
        """sort based on status"""

        #sorted_games = sorted(games, key=lambda k: k['timestamp'])
        sorted_games = sorted(games, key=lambda k: k['ended'])
        
        return sorted_games

    def _replyAsString(self, team, games, tz='US/Eastern', tv=False):
        """parse games and return a string"""
        tmp_dt = '\x02{}\x02: '.format(games[0]['date'])
        
        def _parseStatus(state, inning):
            if not state:
                state = 'F'
            #print(state)
            if 'T' in state or 'B' in state:
                if 'T' in state:
                    resp = '\x033{}{}\x03'.format('↑', inning)
                else:
                    resp = '\x033{}{}\x03'.format('↓', inning)
            elif 'M' in state:
                resp = '\x037{}{}\x03'.format(state, inning)
            elif 'E' in state or 'F' in state:
                if inning == 9 and 'E' not in state:
                    resp = '\x034{}\x03'.format(state)
                elif 'E' in state:
                    resp = '\x037{}{}\x03'.format(state, inning)
                else:
                    resp = '\x034{}/{}\x03'.format(state, inning)
            else:
                resp = '{}{}'.format(state, inning)
            return resp

        def _parseTimezone(time, tz='US/Eastern'):
            if not tz:
                tz = 'US/Eastern'
                
            if 'Game 2' == time:
                return time

            def _checkTarget(target):
                """check input among common tz"""
                target2 = target.upper()
                common = {'CT':  'US/Central',
                        'CDT': 'US/Central',
                        'CST': 'US/Central',
                        'MT':  'US/Mountain',
                        'MDT': 'US/Mountain',
                        'MST': 'US/Mountain',
                        'PT':  'US/Pacific',
                        'PDT': 'US/Pacific',
                        'PST': 'US/Pacific',
                        'ET':  'US/Eastern',
                        'EDT': 'US/Eastern',
                        'EST': 'US/Eastern',
                        'CENTRAL': 'US/Central',
                        'EASTERN': 'US/Eastern',
                        'PACIFIC': 'US/Pacific',
                        'MOUNTAIN': 'US/Mountain'}
                if target2 in common:
                    target = common[target2]
                #print(target)
                return target
            tz = _checkTarget(tz)

            return pendulum.parse(time, strict=False).in_tz(tz).format('h:mm A zz')

        tmp = []
        if len(games) == 1:
            team = True
        for game in games:
            #print(game['homeTeam'], game['status'])
            if game['status'] == 'I':
                status = _parseStatus(game['state'], game['inning'])
                if '↓' in status and game['risp']:
                    if 'Corners' in game['runners'] or 'Loaded' in game['runners'] or '3rd' in game['runners']:
                        game['homeTeam']['abbr'] = '\x034{}\x03'.format(game['homeTeam']['abbr'])
                        game['homeTeam']['full'] = '\x034{}\x03'.format(game['homeTeam']['full'])
                    elif '2nd' in game['runners']:
                        game['homeTeam']['abbr'] = '\x037{}\x03'.format(game['homeTeam']['abbr'])
                        game['homeTeam']['full'] = '\x037{}\x03'.format(game['homeTeam']['full'])
                else:
                    if 'Corners' in game['runners'] or 'Loaded' in game['runners'] or '3rd' in game['runners']:
                        game['awayTeam']['abbr'] = '\x034{}\x03'.format(game['awayTeam']['abbr'])
                        game['awayTeam']['full'] = '\x034{}\x03'.format(game['awayTeam']['full'])
                    elif '2nd' in game['runners']:
                        game['awayTeam']['abbr'] = '\x037{}\x03'.format(game['awayTeam']['abbr'])
                        game['awayTeam']['full'] = '\x037{}\x03'.format(game['awayTeam']['full'])
                if team:
                    away_disp = game['awayTeam']['full']
                    home_disp = game['homeTeam']['full']
                else:
                    away_disp = game['awayTeam']['abbr']
                    home_disp = game['homeTeam']['abbr']
                if game['homeScore'] > game['awayScore']:
                    tmp_st = '{} {} \x02{} {}\x02 {}'.format(away_disp,
                                                            game['awayScore'],
                                                            home_disp,
                                                            game['homeScore'],
                                                            status)
                elif game['awayScore'] > game['homeScore']:
                    tmp_st = '\x02{} {}\x02 {} {} {}'.format(away_disp,
                                                            game['awayScore'],
                                                            home_disp,
                                                            game['homeScore'],
                                                            status)
                else:
                    tmp_st = '{} {} {} {} {}'.format(away_disp,
                                                    game['awayScore'],
                                                    home_disp,
                                                    game['homeScore'],
                                                    status)
                if game['broadcasts'] and tv:
                    if game['broadcasts']['tv'] and game['broadcasts']['radio']:
                        watch = ' [\x02TV:\x02 {} | \x02Radio:\x02 {}]'.format(
                            ', '.join(tv for tv in game['broadcasts']['tv']),
                            ', '.join(radio for radio in game['broadcasts']['radio']))
                    elif game['broadcasts']['tv'] and not game['broadcasts']['radio']:
                        watch = ' [\x02TV:\x02 {}]'.format(
                            ', '.join(tv for tv in game['broadcasts']['tv']))
                    elif not game['broadcasts']['tv'] and game['broadcasts']['radio']:
                        watch = ' [\x02Radio:\x02 {}]'.format(
                            ', '.join(radio for radio in game['broadcasts']['radio']))
                    else:
                        watch = ' [No TV or Radio broadcasts found]'
                    tmp_st += watch
                elif not game['broadcasts'] and tv:
                    tmp_st += ' [No TV or Radio broadcasts found]'
                if team and ('M' not in status and 'E' not in status) and not tv:
                    if game['pitcher'] and game['batter']:
                        pb = ' | \x02P:\x02 {}, \x02AB:\x02 {} '.format(game['pitcher'], game['batter'])
                    else:
                        pb = ''
                    if game['runners']:
                        ro = ' | \x037Runners\x03: {}'.format(game['runners'])
                    else:
                        ro = ''
                    tmp_st += ' | \x033B\x03:{} \x037S\x03:{} \x034O\x03:{}{}{}| {}'
                    tmp_st = tmp_st.format(game['balls'], game['strikes'], game['outs'], ro, pb, game['last'])
                elif team and ('M' in status or 'E' in status) and not tv:
                    tmp_st += ' | {}'
                    tmp_st = tmp_st.format(game['last'])
                #if team:
                    #print(game['id'])
                tmp.append(tmp_st)
            elif ('F' in game['status'] or 'O' in game['status']) and not team:
                status = _parseStatus(game['state'], game['inning'])
                if team:
                    away_disp = game['awayTeam']['full']
                    home_disp = game['homeTeam']['full']
                else:
                    away_disp = game['awayTeam']['abbr']
                    home_disp = game['homeTeam']['abbr']
                if game['homeScore'] > game['awayScore']:
                    tmp_st = '{} {} \x02{} {}\x02 {}'.format(away_disp,
                                                                game['awayScore'],
                                                                home_disp,
                                                                game['homeScore'],
                                                                status)
                elif game['awayScore'] > game['homeScore']:
                    tmp_st = '\x02{} {}\x02 {} {} {}'.format(away_disp,
                                                                game['awayScore'],
                                                                home_disp,
                                                                game['homeScore'],
                                                                status)
                else:
                    tmp_st = '{} {} {} {} {}'.format(away_disp,
                                                                game['awayScore'],
                                                                home_disp,
                                                                game['homeScore'],
                                                                status)
                
                tmp.append(tmp_st)
            elif (game['status'] == 'S' or game['status'] == 'P') and team and not tv:
                if team:
                    away_disp = game['awayTeam']['full']
                    home_disp = game['homeTeam']['full']
                else:
                    away_disp = game['awayTeam']['abbr']
                    home_disp = game['homeTeam']['abbr']
                tmp_st = '{} {} @ {} {} {}'.format(away_disp, game['awayRecord'],
                                                   home_disp, game['homeRecord'],
                                                   game['dt'] if game['dh'] else _parseTimezone(game['dt'], tz))
                pitchers = ' | {} vs {}'.format(game['awayProb'], game['homeProb'])
                tmp_st += pitchers
                #print(game['broadcasts'])
                if game['broadcasts']:
                    if game['broadcasts']['tv'] and game['broadcasts']['radio']:
                        watch = ' | \x02TV:\x02 {} | \x02Radio:\x02 {}'.format(
                            ', '.join(tv for tv in game['broadcasts']['tv']),
                            ', '.join(radio for radio in game['broadcasts']['radio']))
                    elif game['broadcasts']['tv'] and not game['broadcasts']['radio']:
                        watch = ' | \x02TV:\x02 {}'.format(
                            ', '.join(tv for tv in game['broadcasts']['tv']))
                    elif not game['broadcasts']['tv'] and game['broadcasts']['radio']:
                        watch = ' | \x02Radio:\x02 {}'.format(
                            ', '.join(radio for radio in game['broadcasts']['radio']))
                    else:
                        watch = ''
                    tmp_st += watch
                if game['description']:
                    tmp_st += ' | {}'.format(game['description'])
                tmp.append(tmp_st)
            elif ('F' in game['status'] or 'O' in game['status']) and team:
                status = _parseStatus(game['state'], game['inning'])
                if team:
                    away_disp = game['awayTeam']['full']
                    home_disp = game['homeTeam']['full']
                else:
                    away_disp = game['awayTeam']['abbr']
                    home_disp = game['homeTeam']['abbr']
                if game['homeScore'] > game['awayScore']:
                    tmp_st = '{} {} \x02{} {}\x02 {}'.format(away_disp,
                                                                game['awayScore'],
                                                                home_disp,
                                                                game['homeScore'],
                                                                status)
                elif game['awayScore'] > game['homeScore']:
                    tmp_st = '\x02{} {}\x02 {} {} {}'.format(away_disp,
                                                                game['awayScore'],
                                                                home_disp,
                                                                game['homeScore'],
                                                                status)
                else:
                    tmp_st = '{} {} {} {} {}'.format(away_disp,
                                                                game['awayScore'],
                                                                home_disp,
                                                                game['homeScore'],
                                                                status)
                wls_line = ' | \x033W:\x03 {} \x034L:\x03 {}'.format(
                    game['decisions']['W'], game['decisions']['L'])
                if game['decisions'].get('S'):
                    wls_line += ' \x037S:\x03 {}'.format(game['decisions']['S'])
                tmp_st += wls_line
                if game['homers']:
                    hr_str = ' | \x02HR: {}\x02: {} \x02{}\x02: {}'.format(
                        game['awayTeam']['abbr'],
                        ' '.join(item for item in game['homers'][game['awayTeam']['abbr']]),
                        game['homeTeam']['abbr'],
                        ' '.join(item for item in game['homers'][game['homeTeam']['abbr']]))
                    tmp_st += hr_str
                tmp.append(tmp_st)
            elif game['status'] == 'DI' or game['status'] == 'DC' or game['status'] == 'DS' or game['status'] == 'DR' \
            or game['status'] == 'DV' or game['status'] == 'DG':
                if team:
                    away_disp = game['awayTeam']['full']
                    home_disp = game['homeTeam']['full']
                else:
                    away_disp = game['awayTeam']['abbr']
                    home_disp = game['homeTeam']['abbr']
                tmp_st = '{} @ {} \x034PPD\x03'.format(away_disp, home_disp)
                if game['reason'] and team:
                    tmp_st += ' - {}'.format(game['reason'])
                tmp.append(tmp_st)
            # elif game['status'] == 'DI':
            #     tmp_st = '{} @ {} \x034PPD\x03'.format(game['awayTeam'], game['homeTeam'])
            #     if game['reason'] and team:
            #         tmp_st += ' - {}'.format(game['reason'])
            #     tmp.append(tmp_st)
            elif game['status'] == 'PW':
                if team:
                    away_disp = game['awayTeam']['full']
                    home_disp = game['homeTeam']['full']
                else:
                    away_disp = game['awayTeam']['abbr']
                    home_disp = game['homeTeam']['abbr']
                tmp_st = '{} @ {} {} - Warmup'.format(away_disp, home_disp,
                                             _parseTimezone(game['dt'], tz))
                if team:
                    pitchers = ' | {} vs {}'.format(game['awayProb'], game['homeProb'])
                    tmp_st += pitchers
                    tv = True
                if tv:
                    if game['broadcasts']:
                        if game['broadcasts']['tv'] and game['broadcasts']['radio']:
                            watch = ' [\x02TV:\x02 {} | \x02Radio:\x02 {}]'.format(
                                ', '.join(tv for tv in game['broadcasts']['tv']),
                                ', '.join(radio for radio in game['broadcasts']['radio']))
                        elif game['broadcasts']['tv'] and not game['broadcasts']['radio']:
                            watch = ' [\x02TV:\x02 {}]'.format(
                                ', '.join(tv for tv in game['broadcasts']['tv']))
                        elif not game['broadcasts']['tv'] and game['broadcasts']['radio']:
                            watch = ' [\x02Radio:\x02 {}]'.format(
                                ', '.join(radio for radio in game['broadcasts']['radio']))
                        else:
                            watch = ' [No TV or Radio broadcasts found]'
                    else:
                        watch = ' [No TV or Radio broadcasts found]'
                    tmp_st += watch
                tmp.append(tmp_st)
            elif game['status'] == 'PC' or game['status'] == 'PS' or game['status'] == 'PR' or game['status'] == 'PI':
                status = _parseStatus(game['state'], game['inning'])
                if game['homeScore'] > game['awayScore']:
                    if team:
                        away_disp = game['awayTeam']['full']
                        home_disp = game['homeTeam']['full']
                    else:
                        away_disp = game['awayTeam']['abbr']
                        home_disp = game['homeTeam']['abbr']
                    tmp_st = '{} {} \x02{} {}\x02 {}'.format(away_disp,
                                                                game['awayScore'],
                                                                home_disp,
                                                                game['homeScore'],
                                                                status)
                elif game['awayScore'] > game['homeScore']:
                    tmp_st = '\x02{} {}\x02 {} {} {}'.format(away_disp,
                                                                game['awayScore'],
                                                                home_disp,
                                                                game['homeScore'],
                                                                status)
                else:
                    tmp_st = '{} {} {} {} {}'.format(away_disp,
                                                                game['awayScore'],
                                                                home_disp,
                                                                game['homeScore'],
                                                                status)
                tmp_st += ' \x037Delay\x03'
                if game['reason'] and team:
                    tmp_st += ' - {}'.format(game['reason'])
                tmp.append(tmp_st)
            elif game['status'] == 'IW' or game['status'] == 'IC' or game['status'] == 'IS' or game['status'] == 'IR':
                # status = _parseStatus(game['state'], game['inning'])
                if team:
                    away_disp = game['awayTeam']['full']
                    home_disp = game['homeTeam']['full']
                else:
                    away_disp = game['awayTeam']['abbr']
                    home_disp = game['homeTeam']['abbr']
                if game['homeScore'] > game['awayScore']:
                    tmp_st = '{} {} \x02{} {}\x02'.format(away_disp,
                                                                game['awayScore'],
                                                                home_disp,
                                                                game['homeScore'],
                                                                )
                elif game['awayScore'] > game['homeScore']:
                    tmp_st = '\x02{} {}\x02 {} {}'.format(away_disp,
                                                                game['awayScore'],
                                                                home_disp,
                                                                game['homeScore'],
                                                                )
                else:
                    tmp_st = '{} {} {} {}'.format(away_disp,
                                                                game['awayScore'],
                                                                home_disp,
                                                                game['homeScore'],
                                                                )
                tmp_st += ' \x037Delay\x03'
                if game['reason'] and team:
                    tmp_st += ' - {}'.format(game['reason'])
                tmp.append(tmp_st)
            else:
                if team:
                    away_disp = game['awayTeam']['full']
                    home_disp = game['homeTeam']['full']
                else:
                    away_disp = game['awayTeam']['abbr']
                    home_disp = game['homeTeam']['abbr']
                tmp_st = '{} @ {} {}'.format(away_disp, home_disp,
                                             game['dt'] if game['dh'] else _parseTimezone(game['dt'], tz))
                if game['status'] in self._STATUSES.keys() \
                and game['status'] not in ['S', 'P', 'D']:
                    tmp_st += ' - {}'.format(self._STATUSES[game['status']])
                if tv:
                    if game['broadcasts']:
                        if game['broadcasts']['tv'] and game['broadcasts']['radio']:
                            watch = ' [\x02TV:\x02 {} | \x02Radio:\x02 {}]'.format(
                                ', '.join(tv for tv in game['broadcasts']['tv']),
                                ', '.join(radio for radio in game['broadcasts']['radio']))
                        elif game['broadcasts']['tv'] and not game['broadcasts']['radio']:
                            watch = ' [\x02TV:\x02 {}]'.format(
                                ', '.join(tv for tv in game['broadcasts']['tv']))
                        elif not game['broadcasts']['tv'] and game['broadcasts']['radio']:
                            watch = ' [\x02Radio:\x02 {}]'.format(
                                ', '.join(radio for radio in game['broadcasts']['radio']))
                        else:
                            watch = ' [No TV or Radio broadcasts found]'
                    else:
                        watch = ' [No TV or Radio broadcasts found]'
                    tmp_st += watch
                tmp.append(tmp_st)

        if len(tmp) > 1 and team:
            tmp_dt = [tmp_dt + tmp[0]]
            for item in tmp[1:]:
                tmp_dt.append(item)
            return tmp_dt

        tmp_len = len(tmp)
        if tmp_len > 12:
            split_at_pre = ":{}".format(tmp_len // 2)
            split_at_post = "{}:".format(tmp_len // 2)
            split_at = tmp_len // 2
            #print(split_at)
            tmp_dt = (tmp_dt + ' | '.join(item for item in tmp[:split_at]), ' | '.join(item for item in tmp[split_at:]))
        else:
            tmp_dt +=  ' | '.join(item for item in tmp)

        return tmp_dt

    def _parseInput(self, args=None):
        """parse user input from mlb2"""
        # return team, date, timezone

        tz = 'US/Eastern'
        date = None
        team = None
        is_date = None

        if not args:
            return team, date, tz

        arg_array = []
        for arg in args.split(' '):
            arg_array.append(arg)
        
        for idx, arg in enumerate(arg_array):
            #print(arg)
            if '--tz' in arg:
                #print(arg_array[idx+1])
                try:
                    tz = arg_array[idx+1]
                except:
                    tz = 'US/Eastern'
            if arg.lower() in self._FUZZY_DAYS or arg[:3].lower() in self._FUZZY_DAYS:
                date = self._parseDate(arg)
                #print(date)
                #date = pendulum.parse(date).in_tz(tz)
            try:
                arg = arg.strip('-')
                arg = arg.strip('/')
                if arg[0].isdigit() and arg[1].isdigit() and arg[2].isalpha():
                    if arg[-1].isdigit():
                        yr = arg[-2:]
                        mnth = " ".join(re.findall("[a-zA-Z]+", arg))
                        #print(mnth,yr)
                        rebuild = '{}-{}-{}'.format(mnth, arg[:2], yr)
                    else:
                        rebuild = arg[2:] + arg[:2]
                    #print('both', rebuild)
                elif arg[0].isdigit() and arg[1].isalpha():
                    rebuild = arg[1:] + arg[0]
                    #print('one', rebuild)
                else:
                    rebuild = arg
                    
                #print(rebuild)
                is_date = pendulum.parse(rebuild, strict=False)
                #print(is_date)
            except:
                is_date = None
            if is_date:
                date = is_date.format('YYYY-MM-DD')
            if arg.upper() in self._TEAM_BY_TRI:
                team = str(self._TEAM_BY_TRI[arg.upper()])
            elif arg.lower() in self._TEAM_BY_NICK:
                abbr = str(self._TEAM_BY_NICK[arg.lower()])
                team = str(self._TEAM_BY_TRI[abbr])
            # else:
            #     return team, date, tz

        return team, date, tz

    def _parseDate(self, string):
        """parse date"""
        date = string[:3].lower()
        if date in self._FUZZY_DAYS or string.lower() in self._FUZZY_DAYS:
            if date == 'yes':
                date_string = pendulum.yesterday('US/Pacific').format('YYYY-MM-DD')
                #print(date_string)
                return date_string
            elif date == 'tod' or date == 'ton':
                date_string = pendulum.now('US/Pacific').format('YYYY-MM-DD')
                return date_string
            elif date == 'tom':
                date_string = pendulum.tomorrow('US/Pacific').format('YYYY-MM-DD')
                return date_string
            elif date == 'sun':
                date_string = pendulum.now('US/Pacific').next(pendulum.SUNDAY).format('YYYY-MM-DD')
                return date_string
            elif date == 'mon':
                date_string = pendulum.now('US/Pacific').next(pendulum.MONDAY).format('YYYY-MM-DD')
                return date_string
            elif date == 'tue':
                date_string = pendulum.now('US/Pacific').next(pendulum.TUESDAY).format('YYYY-MM-DD')
                return date_string
            elif date == 'wed':
                date_string = pendulum.now('US/Pacific').next(pendulum.WEDNESDAY).format('YYYY-MM-DD')
                return date_string
            elif date == 'thu':
                date_string = pendulum.now('US/Pacific').next(pendulum.THURSDAY).format('YYYY-MM-DD')
                return date_string
            elif date == 'fri':
                date_string = pendulum.now('US/Pacific').next(pendulum.FRIDAY).format('YYYY-MM-DD')
                return date_string
            elif date == 'sat':
                date_string = pendulum.now('US/Pacific').next(pendulum.SATURDAY).format('YYYY-MM-DD')
                return date_string

    def _fetchGames(self, team=None, date=None, league=None):
        """fetches games for mlb2"""

        team = 'all' if not team else team
        #print(team)
        date = pendulum.now('US/Pacific').to_date_string() if not date else date

        if league:
            url = ('https://statsapi.mlb.com/api/v1/schedule'
                                     '?sportId={}&leagueId={}&date={}'
                                     '&hydrate=team(leaders(showOnPreview('
                                     'leaderCategories=[homeRuns,runsBattedIn,'
                                     'battingAverage],statGroup=[pitching,'
                                     'hitting]))),linescore(matchup,runners),'
                                     'flags,liveLookin,review,broadcasts(all),'
                                     'decisions,person,probablePitcher,stats,'
                                     'homeRuns,previousPlay,game(content('
                                     'media(featured,epg),summary),tickets),'
                                     'seriesStatus(useOverride=true)').format(league[0], league[1], date)
        else:
            url = self._SCOREBOARD_ENDPOINT.format(date)

        if 'all' not in team:
            url += '&teamId={}'.format(team)

        #print(url)

        try:
            data = requests.get(url).json()
        except:
            return None

        try:
            games = data['dates'][0]['games']
        except:
            return None

        return games

    def _parseGames(self, games, date, team=None):
        """parse games for mlb2"""
        #print('http://statsapi.mlb.com/api/v1/game/{}/linescore'.format(games[0]['gamePk']))
        
        #print(games)
        if team:
            #date = pendulum.now('US/Pacific').to_date_string() if not date else date
            #games_url = self._SCOREBOARD_ENDPOINT.format(date)
            #games_url += '&teamId={}'.format(team)
            #games = requests.get(games_url).json()
            #print(games_url)
            try:
                #games = games['dates'][0]['games']
                tmpg = []
                for game in games:
                    #print(game['teams']['away']['team']['id'], game['teams']['home']['team']['id'])
                    if str(team) in [str(game['teams']['away']['team']['id']), str(game['teams']['home']['team']['id'])]:
                        tmpg.append(game)
                if tmpg:
                    games = tmpg
                else:
                    return None
            except:
                return None
            
        #print(games)
        
        def _parseLastPlay():
            #print('len:', len(games))
            if len(games) == 1:
                url = 'http://statsapi.mlb.com/api/v1/game/{}/playByPlay'
                #print(url)
                url = url.format(games[0]['gamePk'])
                print(url, 'http://statsapi.mlb.com/api/v1/game/{}/playByPlay'.format(games[0]['gamePk']))
                data = requests.get(url)
                data = data.json()
                plays = reversed(data['allPlays'])
                for play in plays:
                    if play['about']['isComplete'] == True:
                        last_play = play['result']['description']
                        break
            #print(last_play)
            return last_play
        
        def _parseAllAtBats():
            if len(games) == 1:
                url = 'https://statsapi.mlb.com/api/v1.1/game/{}/feed/live'
                #print(url)
                url = url.format(games[0]['gamePk'])
                print(url)
                data = requests.get(url)
                data = data.json()
                plays = data['liveData']['plays']['allPlays']
                #print(len(plays))
                desc = ''
                at_bats = {}
                for play in plays:
                    #print(play)
                    if 'result' in play:
                        if play['result'].get('type') == 'atBat':
                            if play['about'].get('isComplete'):
                                atidx = play['atBatIndex']
                                #print(atidx)
                                res = play['result']['description'].strip()
                                res = ' '.join(res.split())
                                desc = ' | \x02Result:\x02 {} :: {}'.format(play['result']['event'],
                                                         res)
                                #print(desc)
                                count = '\x02B:\x02{} \x02S:\x02{} \x02O:\x02{}'.format(play['count']['balls'],
                                                                play['count']['strikes'],
                                                                play['count']['outs'])
                                #print(count)
                                batter = '\x02AB:\x02 {}'.format(play['matchup']['batter']['fullName'])
                                #print(batter)
                                pitcher = '\x02P:\x02 {}'.format(play['matchup']['pitcher']['fullName'])
                                #print(pitcher)
                                pitches = []
                                pit_num = 0
                                if play['playEvents']:
                                    for idx, pitch in enumerate(play['playEvents']):
                                        if pitch['isPitch']:
                                            pit_num += 1
                                            t = '({}){} - \x02{}mph {}\x02'.format(pit_num, pitch['details']['description'],
                                                                       pitch['pitchData']['startSpeed'],
                                                                       pitch['details']['type']['description'])
                                            pitches.append(t)
                                #print(pitches)
                                at_bat = '{} | {} | {} | {}{}'.format(batter, pitcher, count,
                                                                     ' \x034::\x03 '.join(p for p in pitches),
                                                                     desc)
                                #print(at_bat)
                                at_bats[str(atidx)] = [at_bat, atidx+1, play['matchup']['batter']['fullName']]

            #print(at_bats)
            return at_bats
        
        def _parseAtBat():
            if len(games) == 1:
                url = 'https://statsapi.mlb.com/api/v1.1/game/{}/feed/live'
                #print(url)
                url = url.format(games[0]['gamePk'])
                print(url)
                data = requests.get(url)
                data = data.json()
                play = data['liveData']['plays']['currentPlay']
                #print(play)
                desc = ''
                if 'result' in play:
                    if play['about']['isComplete']:
                        res = play['result']['description'].strip()
                        res = ' '.join(res.split())
                        desc = ' | \x02Result:\x02 {} :: {}'.format(play['result']['event'],
                                                 res)
                #print('desc')
                count = '\x02B:\x02{} \x02S:\x02{} \x02O:\x02{}'.format(play['count']['balls'],
                                                play['count']['strikes'],
                                                play['count']['outs'])
                #print('count')
                batter = '\x02AB:\x02 {}'.format(play['matchup']['batter']['fullName'])
                #print('batter')
                pitcher = '\x02P:\x02 {}'.format(play['matchup']['pitcher']['fullName'])
                #print('pitcher')
                pitches = []
                pit_num = 0
                if play['playEvents']:
                    for idx, pitch in enumerate(play['playEvents']):
                        if pitch['isPitch']:
                            pit_num += 1
                            t = '({}){} - \x02{}mph {}\x02'.format(pit_num, pitch['details']['description'],
                                                       pitch['pitchData']['startSpeed'],
                                                       pitch['details']['type']['description'])
                            pitches.append(t)
                #print('pitches')
                at_bat = '{} | {} | {} | {}{}'.format(batter, pitcher, count,
                                                     ' \x034::\x03 '.join(p for p in pitches),
                                                     desc)

            #print(at_bat)
            return at_bat
                    

        def _parsePitcher(pitcher):
            name = pitcher['lastInitName']
            pitches = pitcher['stats'][1]['stats']['pitchesThrown']
            tmp = '{} ({})'.format(name, pitches)
            return tmp
        
        def _parseBatter(batter):
            name = batter['lastInitName']
            line = '{}/{}'.format(batter['stats'][0]['stats']['hits'], batter['stats'][0]['stats']['atBats'])
            tmp = '{} ({})'.format(name, line)
            return tmp

        def _parseRunners(runners):
            first = True if runners.get('first') else False
            second = True if runners.get('second') else False
            third = True if runners.get('third') else False

            #print(first, second, third)

            if first and not second and not third:
                resp = '1st'
                shrt = '\x039⠠\x03'
                risp = False
            elif first and second and not third:
                resp = '1st and 2nd'
                shrt = '⠢'
                risp = True
            elif first and second and third:
                resp = 'Loaded'
                shrt = '∴'
                risp = True
            elif not first and second and not third:
                resp = '2nd'
                shrt = '⠁'
                risp = True
            elif not first and not second and third:
                resp = "3rd"
                shrt = '\x034⠄\x03'
                risp = True
            elif not first and not second and not third:
                resp = ''
                shrt = ''
                risp = False
            elif first and not second and third:
                resp = 'Corners'
                shrt = '⠤'
                risp = True
            elif not first and second and third:
                resp = '2nd and 3rd'
                shrt = '⠔'
                risp = True
            return resp, shrt, risp

        tmp = []
        for game in games:
            dh = False
            description = None
            gamePk = game['gamePk']
            dt = game['gameDate']
            #print(dt)
            timestamp = pendulum.parse(dt).in_tz('US/Eastern').int_timestamp
            #print(timestamp)
            date = pendulum.parse(game['gameDate']).in_tz('US/Eastern').format('MM/DD/YY')
            time = pendulum.parse(game['gameDate']).in_tz('US/Eastern').format('h:mm A zz')
            #print(date, time)
            status = game['status']['statusCode']
            reason = game['status'].get('reason')
            at_bat = ''
            at_bats = {}
            try:
                description = game['description']
            except:
                description = None
            if game['doubleHeader'] == 'Y' or game['doubleHeader'] == 'S':
                #print('doubleheader')
                if game['gameNumber'] > 1:
                    #print('game 2+')
                    timestamp = pendulum.parse(dt).in_tz('US/Eastern')
                    timestamp = timestamp.add(days=1)
                    timestamp = timestamp.int_timestamp
                    dt = 'Game {}'.format(game['gameNumber'])
                    dh = True
            #print(time)
            try:
                broadcasts = {}
                broadcasts['tv'] = []
                broadcasts['radio'] = []
                for channel in game['broadcasts']:
                    if 'TV' in channel['type']:
                        if 'MLB.com' not in channel['name'] and 'out-of-market' not in channel['name']:
                            broadcasts['tv'].append(channel['name'])
                    elif 'M' in channel['type']:
                        if 'MLB.com' not in channel['name'] and 'out-of-market' not in channel['name']:
                            broadcasts['radio'].append(channel['name'])
                broadcasts['tv'] = [*{*broadcasts['tv']}]
                broadcasts['radio'] = [*{*broadcasts['radio']}]
            except:
                broadcasts = None
            away_team = game['teams']['away']['team']['abbreviation']
            home_team = game['teams']['home']['team']['abbreviation']
            away_full = game['teams']['away']['team']['name']
            home_full = game['teams']['home']['team']['name']
            away_record = '({}-{})'.format(game['teams']['away']['leagueRecord']['wins'],
                                           game['teams']['away']['leagueRecord']['losses'])
            home_record = '({}-{})'.format(game['teams']['home']['leagueRecord']['wins'],
                                           game['teams']['home']['leagueRecord']['losses'])
            try:
                try:
                    away_era = game['teams']['away']['probablePitcher']['stats'][1]['stats']['era']
                    away_wins = game['teams']['away']['probablePitcher']['stats'][1]['stats']['wins']
                    away_loss = game['teams']['away']['probablePitcher']['stats'][1]['stats']['losses']
                    away_line = ' {}/{}-{}'. format(away_era, away_wins, away_loss)
                except:
                    away_line = ''
                try:
                    home_era = game['teams']['home']['probablePitcher']['stats'][1]['stats']['era']
                    home_wins = game['teams']['home']['probablePitcher']['stats'][1]['stats']['wins']
                    home_loss = game['teams']['home']['probablePitcher']['stats'][1]['stats']['losses']
                    home_line = ' {}/{}-{}'. format(home_era, home_wins, home_loss)
                except:
                    home_line = ''
                     
                try:
                    away_prob = '{} ({}HP{})'.format(
                        game['teams']['away']['probablePitcher']['lastInitName'],
                        game['teams']['away']['probablePitcher']['pitchHand']['code'],
                        away_line)
                except:
                    away_prob = 'TBD'
                try:
                    home_prob = '{} ({}HP{})'.format(
                        game['teams']['home']['probablePitcher']['lastInitName'],
                        game['teams']['home']['probablePitcher']['pitchHand']['code'],
                        home_line)
                except:
                    home_prob = 'TBD'
            except:
                away_prob = 'TBD'
                home_prob = 'TBD'
            away_score = game['teams']['away'].get('score')
            home_score = game['teams']['home'].get('score')
            #print('scores', away_score, home_score)
            if not away_score:
                away_score = 0
            if not home_score:
                home_score = 0
            try:
                inning = game['linescore'].get('currentInning')
            except:
                inning = 1
            try:
                state = game['linescore'].get('inningState')
            except:
                state = None
            #print(state)
            balls = '0'
            strikes = '0'
            outs = '0'
            pitcher = None
            batter = None
            runners = None
            short_runners = None
            risp = False
            if not state:
                if 'F' in status or 'O' in status:
                    state = 'F'
                    ended = True
                    last_play = ''
                elif status == 'DI' or status == 'DC' or status == 'DS' or status == 'DR' \
                or status == 'DV' or status == 'DG':
                    state = state
                    ended = True
                    last_play = ''
                else:
                    state = None
                    ended = False
                    last_play = ''
            else:
                if 'F' in status or 'O' in status:
                    state = 'F'
                    ended = True
                    last_play = ''
                elif status == 'DI' or status == 'DC' or status == 'DS' or status == 'DR' \
                or status == 'DV' or status == 'DG':
                    state = state
                    ended = True
                    last_play = ''
                else:
                    state = state[:1]
                    ended = False
                    if 'I' in status:
                        try:
                            pitcher = _parsePitcher(game['linescore']['defense']['pitcher'])
                        except:
                            pitcher = None
                        try:
                            batter = _parseBatter(game['linescore']['offense']['batter'])
                        except:
                            batter = None
                        try:
                            runners, short_runners, risp = _parseRunners(game['linescore']['offense'])
                        except:
                            runners = None
                            short_runners = None
                            risp = False
                        try:
                            try:
                                last_play = _parseLastPlay()
                                last_play = last_play.strip()
                                last_play = " ".join(last_play.split())
                            except:
                                last_play = game['previousPlay']['result'].get('description').strip()
                                last_play = " ".join(last_play.split())
                        except:
                            last_play = ''

                        try:
                            at_bat = _parseAtBat()
                        except:
                            at_bat = ''
                        try:
                            at_bats = _parseAllAtBats()
                        except:
                            at_bats = {}
                        try:
                            balls = str(game['linescore']['balls'])
                        except:
                            balls = balls
                        try:
                            strikes = str(game['linescore']['strikes'])
                        except:
                            strikes = strikes
                        try:
                            outs = str(game['linescore']['outs'])
                        except:
                            outs = outs
                    else:
                        last_play = ''
                        at_bat = ''
                        at_bats = {}
            if 'F' in status or 'O' in status:
                decisions = {}
                try:
                    decisions['W'] = '{} ({}/{}-{})'.format(
                        game['decisions']['winner']['lastInitName'],
                        game['decisions']['winner']['stats'][3]['stats']['era'],
                        game['decisions']['winner']['stats'][3]['stats']['wins'],
                        game['decisions']['winner']['stats'][3]['stats']['losses'])
                except:
                    decisions['W'] = 'TBD'
                try:
                    decisions['L'] = '{} ({}/{}-{})'.format(
                        game['decisions']['loser']['lastInitName'],
                        game['decisions']['loser']['stats'][3]['stats']['era'],
                        game['decisions']['loser']['stats'][3]['stats']['wins'],
                        game['decisions']['loser']['stats'][3]['stats']['losses'])
                except:
                    decisions['L'] = 'TBD'
                try:
                    save = game['decisions'].get('save')
                except:
                    save = None
                if save:
                    decisions['S'] = '{} ({}/{}-{}/{}-{})'.format(
                        save['lastInitName'],
                        save['stats'][3]['stats']['era'],
                        save['stats'][3]['stats']['wins'],
                        save['stats'][3]['stats']['losses'],
                        save['stats'][3]['stats']['saves'],
                        save['stats'][3]['stats']['blownSaves'])
                homers = {}
                homeRuns = game.get('homeRuns')
                if homeRuns:
                    homers[away_team] = []
                    homers[home_team] = []
                    for item in homeRuns:
                        #print(item)
                        try:
                            name = item['matchup']['batter']['lastInitName']
                        except:
                            name = item['matchup']['batter']['fullName']
                        num = item['matchup']['batter']['stats'][2]['stats']['homeRuns']
                        string = '{}({})'.format(name,num)
                        if 'top' in item['about']['halfInning']:
                            homers[away_team].append(string)
                        elif 'bot' in item['about']['halfInning']:
                            homers[home_team].append(string)
                    
                    if not homers[away_team]:
                        homers[away_team] = ['None']
                    if not homers[home_team]:
                        homers[home_team] = ['None']
                    
                    if homers[away_team]:
                        #print('hi')
                        homers[away_team] = [*{*homers[away_team]}]
                    if homers[home_team]:
                        #print('bye')
                        homers[home_team] = [*{*homers[home_team]}]

            else:
                homers = None
                decisions = None
            #print(time)
            tmp.append({'id': gamePk, 'date': date, 'time': time, 'dt': dt, 'dh': dh, 'timestamp': timestamp,
                        'awayTeam': {'abbr': away_team, 'full': away_full}, 'awayScore': away_score,
                        'homeTeam': {'abbr': home_team, 'full': home_full}, 'homeScore': home_score,
                        'inning': inning, 'state': state, 'last': last_play, 'atBat': at_bat, 'atBats': at_bats,
                        'status': status, 'reason': reason, 'broadcasts': broadcasts, 'ended': ended,
                        'balls': balls, 'strikes': strikes, 'outs': outs,
                        'pitcher': pitcher, 'batter': batter, 'runners': runners, 'sh_runs': short_runners, 'risp': risp,
                        'awayRecord': away_record, 'homeRecord': home_record,
                        'awayProb': away_prob, 'homeProb': home_prob,
                        'decisions': decisions, 'homers': homers, 'description': description})

        return(tmp)

Class = MLBScores


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