import os
import sys
import time
import json
import requests
from struct import pack
from base64 import b64encode

import gw2api


__all__ = ("encode_item_link", "encode_coin_link", "encode_chat_link")


def mtime(path):
    """Get the modification time of a file, or -1 if the file does not exist.
    """
    if not os.path.exists(path):
        return -1
    stat = os.stat(path)
    return stat.st_mtime


def get_cached(path, cache_name=None, **kwargs):
    """Request a resource form the API, first checking if there is a cached
    response available. Returns the parsed JSON data.
    """
    if gw2api.cache_dir and gw2api.cache_time and cache_name is not False:
        if cache_name is None:
            cache_name = path
        cache_file = os.path.join(gw2api.cache_dir, cache_name)
        if mtime(cache_file) >= time.time() - gw2api.cache_time:
            with open(cache_file, "r") as fp:
                return json.load(fp)
    else:
        cache_file = None

    r = gw2api.session.get(gw2api.BASE_URL + path, **kwargs)
    r.raise_for_status()
    data = r.json()

    if cache_file:
        with open(cache_file, "w") as fp:
            json.dump(data, fp, indent=2)

    return data


def encode_item_link(item_id, number=1):
    """Encode a chat link for an item (or a stack of items).

    :param item_id: the Id of the item
    :param number: the number of items in the stack
    """
    return encode_chat_link(gw2api.TYPE_ITEM, id=item_id, number=number)


def encode_coin_link(copper, silver=0, gold=0):
    """Encode a chat link for an amount of coins.
    """
    amount = copper + silver * 100 + gold * 100 * 100
    return encode_chat_link(gw2api.TYPE_COIN, amount=amount)


def encode_chat_link(link_type, **kwargs):
    if isinstance(link_type, basestring):
        link_type = gw2api.LINK_TYPES[link_type]

    if link_type == gw2api.TYPE_COIN:
        if "copper" in kwargs or "silver" in kwargs or "gold" in kwargs:
            amount = (kwargs.get("gold", 0) * 100 * 100 +
                      kwargs.get("silver", 0) * 100 +
                      kwargs.get("copper", 0))
        else:
            amount = kwargs["amount"]
        data = pack("<BI", link_type, amount)
    elif link_type == gw2api.TYPE_ITEM:
        data = pack("<BBI", link_type, kwargs.get("number", 1), kwargs["id"])
    elif link_type in (gw2api.TYPE_TEXT, gw2api.TYPE_MAP, gw2api.TYPE_SKILL,
                       gw2api.TYPE_TRAIT, gw2api.TYPE_RECIPE,
                       gw2api.TYPE_SKIN, gw2api.TYPE_OUTFIT):
        data = pack("<BI", link_type, kwargs["id"])
    else:
        raise Exception("Unknown link type 0x%02x" % link_type)

    return "[&%s]" % b64encode(data)

@@ -1242,16 +1242,60 @@
 number=1
+, skin_id=None, upgrade1=None, upgrade2=None
 ):%0A    %22
@@ -1450,83 +1450,372 @@
     
-%22%22%22%0A    return encode_chat_link(gw2api.TYPE_ITEM, id=item_id, number=number
+:param skin_id: the id of the skin applied to the item%0A    :param upgrade1: the id of the first upgrade component%0A    :param upgrade2: the id of the second upgrade component%0A    %22%22%22%0A    return encode_chat_link(gw2api.TYPE_ITEM, id=item_id, number=number,%0A                            skin_id=skin_id, upgrade1=upgrade1,%0A                            upgrade2=upgrade2
 )%0A%0A%0A
@@ -2540,16 +2540,17 @@
 amount)%0A
+%0A
     elif
@@ -2593,26 +2593,323 @@
     
-data = pack(%22%3CBBI%22
+item_id = kwargs%5B%22id%22%5D%0A%0A        args = %5B%5D%0A        for i, key in enumerate((%22skin_id%22, %22upgrade1%22, %22upgrade2%22)):%0A            value = kwargs.get(key)%0A            if value:%0A                item_id %7C= 2 %3C%3C (28 + i)%0A                args.append(value)%0A%0A        format = %22%3CBBI%22 + %22I%22 * len(args)%0A        data = pack(format
 , li
@@ -2942,29 +2942,32 @@
 r%22, 1), 
-kwargs%5B%22id%22%5D)
+item_id, *args)%0A
 %0A    eli
@@ -3212,16 +3212,17 @@
 %5B%22id%22%5D)%0A
+%0A
     else

add support for skin and upgrades in item chat links