import requests
from bs4 import BeautifulSoup  # MIT
import urllib.parse


class Game:
    def __init__(self, name,link,img):
        self.name = name.strip()
        self.link = link.strip()
        self.img = img.strip()
        if not name or not link or not img:
            raise ValueError("Please enter a name, link and img!")

    def __eq__(self, other):
        return self.name == other.name and self.link == other.link and self.img == other.img

    def get_csv_line(self):
        return f"{self.name};{self.link};{self.img}"

class ModuleFreeGames:
    def __init__(self, subscriber, send_a, log):
        self.tag = "%20s - " % "mFreeGames"
        self.log = log

        self.game_dict = self.load_freegames_from_csv()
        self.subscriber = subscriber
        self.send_a = send_a

        self.log.debug(f"{self.tag}Modul FreeGames geladen")

    def crawl_game_list(self):
        temp_dict = {}
        try:
            data = requests.get("https://www.freegamesyo.com/").text
            soup = BeautifulSoup(data, features="html.parser")

            number = 0
            for li in soup.find_all('li'):
                link = li.a['href']
                name = li.find('h2').text
                img = li.find('noscript').find('img')
                src = img['src']
                if name not in temp_dict:
                    game = Game(name, link, f"game_{number}.jpeg")
                    img_link = "https://www.freegamesyo.com"+urllib.parse.unquote(src)
                    img_data = requests.get(img_link).content
                    with open(game.img, 'wb') as handler:  # can be overwritten because this will be the new list
                        handler.write(img_data)
                    temp_dict[name] = game
                    number += 1
        except Exception as ex:
            self.log.error(f"{self.tag}Failed crawling game list: {ex}")

        self.save_gamelist(temp_dict)
        return temp_dict

    def check_for_new_stuff(self):
        new = self.crawl_game_list()
        send_update = False

        for game in new:
            if game not in self.game_dict:
                send_update = True
                break

        self.game_dict = new  # always overwrite to delete old games
        return send_update

    def auto_newsletter(self):
        send_update = self.check_for_new_stuff()
        if send_update:
            self.send_newsletter()

    def send_newsletter(self):
        for receiver in self.subscriber.values():
            self.send_game(receiver)

    def send_game(self, receiver):
        for game in self.game_dict.values():
            message = game.name + ":\n"
            message += game.link + " "
            self.send_a(message, receiver, f"/home/pi/signalbot/" + game.img)
            #self.send(message, receiver)

    def freegames(self, receiver):
        send_update = self.check_for_new_stuff()
        if send_update:
            if receiver in self.subscriber.values():
                self.send_newsletter()
            else:
                self.send_game(receiver)
                self.send_newsletter()
        else:
            self.send_game(receiver)

    def load_freegames_from_csv(self):
        lines = []
        try:
            with open("/home/pi/signalbot/freegameslist.csv", 'r', encoding='utf16') as f:
                lines = f.readlines()
        except IOError as exc:
            self.log.error(
                f"{self.tag}Reading freegameslist from csv failed: {exc}")
        temp_dict = {}

        for line in lines:
            try:
                game = self.interpret_game_line(line)
                temp_dict[game.name] = game
            except (SyntaxError, ValueError) as exc:
                self.log.warning(f"{self.tag}Error while interpreting game line:{line}; Error: {exc}")

        return temp_dict

    def interpret_game_line(self, line):
        splitted = line.strip().split(";")
        if not (len(splitted) == 3):
            raise SyntaxError("Invalid game syntax! Needs to be: 'name;link;img_filename'")

        return Game(splitted[0].strip(), splitted[1].strip(), splitted[2].strip())


    def save_gamelist(self, gamelist):
        try:
            with open("/home/pi/signalbot/freegameslist.csv", 'w', encoding='utf16') as f:
                for game in gamelist.values():
                    f.write(f"{game.name};{game.link};{game.img}\n")
        except IOError as exc:
            self.log.error(f"{self.tag}saving game to '/home/pi/signalbot/freegameslist.csv' failed: {exc}")