import debug
import time
import feedparser
from datetime import datetime
from dates import Dates

try:
  from HTMLParser import HTMLParser
except ImportError:
  from html.parser import HTMLParser


HEADLINE_UPDATE_RATE = 60 * 60 # 1 hour between feed updates
HEADLINE_SPACER_SIZE = 10 # Number of spaces between headlines
HEADLINE_MAX_FEEDS = 3 # Number of preferred team's feeds to fetch
HEADLINE_MAX_ENTRIES = 7 # Number of headlines per feed
FALLBACK_DATE_FORMAT = "%A, %B %-d"


MLB_BASE = "https://www.mlb.com"
MLB_PATH = "feeds/news/rss.xml"
MLB_FEEDS = {
  "MLB": "", "Angels": "angels", "Astros": "astros", "Athletics": "athletics", "Blue Jays": "bluejays", 
  "Indians": "indians", "Mariners": "mariners", "Orioles": "orioles", "Rangers": "rangers", "Rays": "rays", 
  "Red Sox": "redsox", "Royals": "royals", "Tigers": "tigers", "Twins": "twins", "White Sox": "whitesox", 
  "Yankees": "yankees", "Braves": "braves", "Brewers": "brewers", "Cardinals": "cardinals", "Cubs": "cubs", 
  "Diamondbacks": "dbacks", "D-Backs": "dbacks", "Dodgers": "dodgers", "Giants": "giants", "Marlins": "marlins", 
  "Mets": "mets", "Nationals": "nationals", "Padres": "padres", "Phillies": "phillies", "Pirates": "pirates",
  "Reds": "reds", "Rockies": "rockies"
}

TRADE_BASE = "https://www.mlbtraderumors.com"
TRADE_PATH = "feed/atom"
TRADE_FEEDS = {
  "Angels": "los-angeles-angels-of-anaheim",
  "Astros": "houston-astros",
  "Athletics": "oakland-athletics",
  "Blue Jays": "toronto-blue-jays",
  "Indians": "cleveland-indians",
  "Mariners": "seattle-mariners",
  "Orioles": "baltimore-orioles",
  "Rangers": "texas-rangers",
  "Rays": "tampa-bay-devil-rays",
  "Red Sox": "boston-red-sox",
  "Royals": "kansas-city-royals",
  "Tigers": "detroit-tigers",
  "Twins": "minnesota-twins",
  "White Sox": "chicago-white-sox",
  "Yankees": "new-york-yankees",
  "Braves": "atlanta-braves",
  "Brewers": "milwaukee-brewers",
  "Cardinals": "st-louis-cardinals",
  "Cubs": "chicago-cubs",
  "Diamondbacks": "arizona-diamondbacks",
  "D-Backs": "arizona-diamondbacks",
  "Dodgers": "los-angeles-dodgers",
  "Giants": "san-francisco-giants",
  "Marlins": "florida-marlins",
  "Mets": "new-york-mets",
  "Nationals": "washington-nationals",
  "Padres": "san-diego-padres",
  "Phillies": "philadelphia-phillies",
  "Pirates": "pittsburgh-pirates",
  "Reds": "cincinnati-reds",
  "Rockies": "colorado-rockies"
}

class Headlines:

  def __init__(self, config):
    self.preferred_teams = config.preferred_teams
    self.include_mlb = config.news_ticker_mlb_news
    self.include_preferred = config.news_ticker_preferred_teams
    self.include_traderumors = config.news_ticker_traderumors
    self.include_countdowns = config.news_ticker_countdowns
    self.include_date = config.news_ticker_date
    self.date_format = config.news_ticker_date_format
    self.feed_urls = []
    self.feed_data = None
    self.starttime = time.time()
    self.important_dates = Dates()

    self.__compile_feed_list()
    self.update(True)

  def update(self, force=False):
    if force == True or self.__should_update():
      debug.log("Headlines should update!")
      self.starttime = time.time()
      feeds = []
      debug.log("{} feeds to update...".format(len(self.feed_urls)))
      feedparser.USER_AGENT = "mlb-led-scoreboard/3.0 +https://github.com/MLB-LED-Scoreboard/mlb-led-scoreboard"
      if len(self.feed_urls) > 0:
        debug.log("Feed URLs found...")
        for idx, url in enumerate(self.feed_urls):
          if idx < HEADLINE_MAX_FEEDS: # Only parse MAX teams to prevent potential hangs
            debug.log("Fetching {}".format(url))
            f = feedparser.parse(url)
            try:
              title = f.feed.title.encode("ascii", "ignore")
              debug.log("Fetched feed '{}' with {} entries.".format(title, len(f.entries)))
              feeds.append(f)
            except AttributeError:
              debug.warning("There was a problem fetching {}".format(url))
        self.feed_data = feeds

  def ticker_string(self, max_entries=HEADLINE_MAX_ENTRIES):
    ticker = ""
    if self.include_date:
      date_string = datetime.now().strftime(self.date_format)
      ticker = self.__add_string_to_ticker(ticker, date_string)

    if self.include_countdowns:
      countdown_string = self.important_dates.next_important_date_string()

      # If we get None back from this method, we don't have an important date coming soon
      if countdown_string is not None:
        ticker = self.__add_string_to_ticker(ticker, countdown_string)

    if self.feed_data != None:
      ticker = self.__add_string_to_ticker(ticker, "")
      for feed in self.feed_data:
        ticker += self.__strings_for_feed(feed, max_entries)

    # In case all of the ticker options are turned off and there's no data, return the date
    return datetime.now().strftime(FALLBACK_DATE_FORMAT) if len(ticker) < 1 else ticker

  def __add_string_to_ticker(self, ticker, text_to_add):
    t = ticker
    if len(t) > 0:
      t += (" " * HEADLINE_SPACER_SIZE)
    return (t + text_to_add)

  def available(self):
    return self.feed_data != None

  def __strings_for_feed(self, feed, max_entries):
    spaces = " " * HEADLINE_SPACER_SIZE
    title = feed.feed.title.encode("ascii", "ignore")
    headlines = ""

    for idx, entry in enumerate(feed.entries):
      if idx < max_entries:
        h = HTMLParser()
        text = h.unescape(entry.title.encode("ascii", "ignore"))
        headlines += text + spaces
    return title + spaces + headlines

  def __compile_feed_list(self):
    if self.include_mlb:
      self.feed_urls.append(self.__mlb_url_for_team("MLB"))

    if self.include_preferred:
      if len(self.preferred_teams) > 0:
        for team in self.preferred_teams:
          self.feed_urls.append(self.__mlb_url_for_team(team))

    if self.include_traderumors:
      if len(self.preferred_teams) > 0:
        for team in self.preferred_teams:
          self.feed_urls.append(self.__traderumors_url_for_team(team))

  def __mlb_url_for_team(self, team_name):
    return "{}/{}/{}".format(MLB_BASE, MLB_FEEDS[team_name], MLB_PATH)

  def __traderumors_url_for_team(self, team_name):
    return "{}/{}/{}".format(TRADE_BASE, TRADE_FEEDS[team_name], TRADE_PATH)

  def __should_update(self):
    endtime = time.time()
    time_delta = endtime - self.starttime
    return time_delta >= HEADLINE_UPDATE_RATE