import json, urllib.request

class Arena:

    def __init__(self, arena_id: int):
        self.arena_id = arena_id

    @property
    def data(self):
        with urllib.request.urlopen("http://api.cr-api.com/constants") as url:
            data = json.loads(url.read().decode())
        for test_arena in data['arenas']:
            if self.arena_id == test_arena['arenaID']:
                return test_arena
        return None

    @property
    def exists(self):
        if data == None:
            return False
        return True

    @property
    def number(self):
        if not self.exists:
            return None
        return self.data['arena']

    @property
    def name(self):
        if not self.exists:
            return None
        return self.data['name']

    @property
    def trophies_required(self):
        if not self.exists:
            return None
        return self.data['trophyLimit']

    @property
    def img_url(self):
        if not self.exists:
            return None
        return "http://api.cr-api.com/arena/{}.png".format(self.number.replace(" ", "").lower())

class Profile:

    def __init__(self, tag: str):
        self.tag = tag

    @property
    def data(self):
        with urllib.request.urlopen("http://api.cr-api.com/profile/{}".format(self.tag)) as url:
            if "error" in json.loads(url.read().decode()):
                return None
            return json.loads(url.read().decode())

    @property
    def exists(self):
        if self.data == None:
            return False
        return True

    class Cycles:

        def __init__(self, data):
            self.data = data

        @property
        def chest_pos(self):
            return self.data['chestCycle']['chest_position']

        @property
        def smc_pos(self):
            return self.data['chestCycle']['superMagicalPos']

        @property
        def leg_pos(self):
            return self.data['chestCycle']['legendaryPos']

        @property
        def epic_pos(self):
            return self.data['chestCycle']['epicPos']

        @property
        def leg_shop(self):
            return self.data['shopOffers']['legendary']

        @property
        def epic_shop(self):
            return self.data['shopOffers']['epic']

        @property
        def arena_shop(self):
            return self.data['shopOffers']['arena']

    class XP:

        def __init__(self, data):
            self.data = data

        @property
        def current(self):
            return self.data['experience']['xp']

        @property
        def required(self):
            return self.data['experience']['xpRequiredForLevelUp']

        @property
        def remaining(self):
            return self.data['experience']['xpToLevelUp']

    class Trophies:

        def __init__(self, data):
            self.data = data

        @property
        def current(self):
            return self.data['trophies']

        @property
        def record(self):
            return self.data['stats']['maxTrophies']

        @property
        def legendary(self):
            return self.data['legendaryTrophies']

    class Cards:

        def __init__(self, data):
            self.data = data

        @property
        def found(self):
            return self.data['stats']['cardsFound']

        @property
        def tournament(self):
            return self.data['stats']['tournamentCardsWon']

        @property
        def favorite(self):
            return Card(key=self.data['stats']['favoriteCard'])

        @property
        def challenge(self):
            return self.data['stats']['challengeCardsWon']

    class Games:

        def __init__(self, data):
            self.data = data

        @property
        def total_games(self):
            return self.data['games']['total']

        @property
        def tournament_games(self):
            return self.data['games']['tournamentGames']

        @property
        def wins(self):
            return self.data['games']['wins']

        @property
        def losses(self):
            return self.data['games']['losses']

        @property
        def draws(self):
            return self.data['games']['draws']

        @property
        def three_crowns(self):
            return self.data['stats']['threeCrownWins']

        @property
        def win_streak(self):
            if self.data['games']['currentWinStreak'] < 0:
                return 0
            else:
                return self.data['games']['currentWinStreak']

    @property
    def cycles(self):
        if not self.exists:
            return None
        return self.Cycles(self.data)

    @property
    def xp(self):
        if not self.exists:
            return None
        return self.XP(self.data)

    @property
    def trophies(self):
        if not self.exists:
            return None
        return self.Trophies(self.data)

    @property
    def cards(self):
        if not self.exists:
            return None
        return self.Cards(self.data)

    @property
    def games(self):
        if not self.exists:
            return None
        return self.Games(self.data)

    @property
    def name(self):
        if not self.exists:
            return None
        return self.data['name']

    @property
    def arena(self):
        if not self.exists:
            return None
        return Arena(arena_id=self.data['arena']['arenaID'])

    @property
    def name_changed(self):
        if not self.exists:
            return None
        return self.data['nameChanged']

    @property
    def global_rank(self):
        if not self.exists:
            return None
        return self.data['globalRank']

    @property
    def clan(self):
        if not self.exists:
            return None
        return Clan(self.data['clan']['tag']) or None

    @property
    def clan_chest_contrib(self):
        if not self.exists:
            return None
        try:
            return [x['clanChestCrowns'] for x in self.clan.members if x.name==self.name][0]
        except:
            return None

    @property
    def level(self):
        if not self.exists:
            return None
        return self.data['experience']['level']

    @property
    def account_age(self):
        if not self.exists:
            return None
        return self.data['stats']['accountAgeInDays']

    @property
    def total_donations(self):
        if not self.exists:
            return None
        return self.data['stats']['totalDonations']

    @property
    def challenge_record(self):
        if not self.exists:
            return None
        return self.data['stats']['challengeMaxWins']

    @property
    def deck(self):
        if not self.exists:
            return None
        deck = []
        for card in self.data['currentDeck']:
            card_name = card.name.replace("_", "-")
            if card_name == "x-bow":
                deck.append((Card("bow"), card.level))
            else:
                deck.append((Card(card_name), card.level))
        return deck

class Clan:

    def __init__(self, tag: str):
        self.tag = tag

    @property
    def data(self):
        with urllib.request.urlopen("http://api.cr-api.com/clan/{}".format(self.tag)) as url:
            if "error" in json.loads(url.read().decode()):
                return None
            return json.loads(url.read().decode())

    @property
    def exists(self):
        if self.data == None:
            return False
        return True

    class ClanChest:

        def __init__(self, data):
            self.data = data

        @property
        def required(self):
            return self.data['clanChest']['clanChestCrownsRequired']

        @property
        def crowns(self):
            return self.data['clanChest']['clanChestCrowns']

        @property
        def finished_percent(self):
            return self.data['clanChest']['clanChestCrownsPercent']*100

    class Trophies:

        def __init__(self, data):
            self.data = data

        @property
        def current(self):
            return self.data['score']

        @property
        def requirement(self):
            return self.data['requiredScore']

    @property
    def clanchest(self):
        if not self.exists:
            return None
        return self.ClanChest(self.data)

    @property
    def trophies(self):
        if not self.exists:
            return None
        return self.Trophies(self.data)

    @property
    def members(self):
        if not self.exists:
            return None
        return [Profile(x['tag']) for x in self.data['members']]

    @property
    def name(self):
        if not self.exists:
            return None
        return self.data['name']

    @property
    def badge_url(self):
        if not self.exists:
            return None
        return "api.cr-api.com/{0}".format(self.data['badge']['url'])

    @property
    def type(self):
        if not self.exists:
            return None
        return self.data['typeName']

    @property
    def member_count(self):
        if not self.exists:
            return None
        return self.data['memberCount']

    @property
    def donations(self):
        return self.data['donations']

    @property
    def rank(self):
        if self.data['currentRank'] == 0:
            return None
        return self.data['currentRank']

    @property
    def description(self):
        return self.data['description']

    @property
    def region(self):
        return self.data['region']['name']


class Card:

    def __init__(self, key):
        self.key = key

    @property
    def data(self):
        with urllib.request.urlopen("https://raw.githubusercontent.com/smlbiobot/cr-api-data/master/dst/cards.json") as url:
            data = json.loads(url.read().decode())
        for test_card in data:
            if self.key == test_card['key']:
                return test_card
        return None

    @property
    def exists(self):
        if self.data == None:
            return False
        return True

    @property
    def name(self):
        if not self.exists:
            return None
        return self.data['name']

    @property
    def elixir(self):
        if not self.exists:
            return None
        return self.data['elixir']

    @property
    def type(self):
        if not self.exists:
            return None
        return self.data['type']

    @property
    def rarity(self):
        if not self.exists:
            return None
        return self.data['rarity']

    @property
    def arena_found(self):
        if not self.exists:
            return None
        return self.data['arena']

    @property
    def description(self):
        if not self.exists:
            return None
        return self.data['description']

    @property
    def card_id(self):
        if not self.exists:
            return None
        return self.data['decklink']

    @property
    def img_url(self):
        if not self.exists:
            return None
        return "https://raw.githubusercontent.com/cr-api/cr-api-assets/master/card/{}.png".format(self.key)
