from bittrex import Bittrex
import json
import time
import os
import unirest
from twilio.rest import Client

# Creating an instance of the Bittrex class with our secrets.json file
# with open("secrets.json") as secrets_file:
#     secrets = json.load(secrets_file)
#     secrets_file.close()
bittrex_key = os.getenv('BITTREX_KEY', '')
bittrex_secret = os.getenv('BITTREX_SECRET', '')
my_bittrex = Bittrex(bittrex_key, bittrex_secret)

# Setting up Twilio for SMS alerts
# account_sid = secrets['twilio_key']
# auth_token = secrets['twilio_secret']
# client = Client(account_sid, auth_token)


# Let's test an API call to get our BTC balance as a test
# print(my_bittrex.get_balance('BTC')['result']['Balance'])

coin_pairs = ['BTC-ETH']

#print(historical_data = my_bittrex.getHistoricalData('BTC-ETH', 30, "thirtyMin"))
def getClosingPrices(coin_pair, period, unit):
    """
    Returns closing prices within a specified time frame for a coin pair
    :type coin_pair: str
    :type period: str
    :type unit: int
    :return: Array of closing prices
    """

    historical_data = my_bittrex.getHistoricalData(coin_pair, period, unit)
    closing_prices = []
    for i in historical_data:
        closing_prices.append(i['C'])
    return closing_prices

def getRangeClosingPrices(coin_pair, period_from, period_to, unit):
    historical_data = my_bittrex.getRangeHistoricalData(coin_pair, period_from, period_to, unit)
    closing_prices = []
    for i in historical_data:
        closing_prices.append(i['C'])
    return closing_prices

def calculateSMA(coin_pair, period, unit):
    """
    Returns the Simple Moving Average for a coin pair
    """

    total_closing = sum(getClosingPrices(coin_pair, period, unit))
    return (total_closing / period)

def calculateEMA(coin_pair, period, unit):
    """
    Returns the Exponential Moving Average for a coin pair
    """

    closing_prices = getClosingPrices(coin_pair, period, unit)
    previous_EMA = calculateSMA(coin_pair, period, unit)
    constant = (2 / (period + 1))
    current_EMA = (closing_prices[-1] * (2 / (1 + period))) + (previous_EMA * (1 - (2 / (1 + period))))
    return current_EMA

def calculateRSI(coin_pair, period, unit):
    """
    Calculates the Relative Strength Index for a coin_pair
    If the returned value is above 70, it's overbought (SELL IT!)
    If the returned value is below 30, it's oversold (BUY IT!)
    """
    closing_prices = getClosingPrices(coin_pair, period, unit)
    count = 0
    change = []
    # Calculating price changes
    for i in closing_prices:
        if count != 0:
            change.append(i - closing_prices[count - 1])
        count += 1
    # Calculating gains and losses
    advances = []
    declines = []
    for i in change:
        if i > 0:
            advances.append(i)
        if i < 0:
            declines.append(abs(i))
    average_gain = (sum(advances) / len(advances))
    average_loss = (sum(declines) / len(declines))
    relative_strength = (average_gain / average_loss)
    if change[-1] >= 0:
        smoothed_rs = (((average_gain * 13) + change[-1]) / 14) / (((average_loss * 13) + 0) / 14)
    if change[-1] < 0:
        smoothed_rs = (((average_gain * 13) + 0) / 14) / (((average_loss * 13) + abs(change[-1])) / 14)
    RSI = 100 - (100 / (1 + smoothed_rs))
    return RSI


def calculateBaseLine(coin_pair, unit):
    """
    Calculates (26 period high + 26 period low) / 2
    Also known as the "Kijun-sen" line
    """

    closing_prices = getClosingPrices(coin_pair, 26, unit)
    period_high = max(closing_prices)
    period_low = min(closing_prices)
    return (period_high + period_low) / 2

def calculateConversionLine(coin_pair, unit):
    """
    Calculates (9 period high + 9 period low) / 2
    Also known as the "Tenkan-sen" line
    """
    closing_prices = getClosingPrices(coin_pair, 9, unit)
    period_high = max(closing_prices)
    period_low = min(closing_prices)
    return (period_high + period_low) / 2

def calculateLeadingSpanA(coin_pair, unit):
    """
    Calculates (Conversion Line + Base Line) / 2
    Also known as the "Senkou Span A" line
    """

    base_line = calculateBaseLine(coin_pair, unit)
    conversion_line = calculateConversionLine(coin_pair, unit)
    return (base_line + conversion_line) / 2

def calculateLeadingSpanB(coin_pair, unit):
    """
    Calculates (52 period high + 52 period low) / 2
    Also known as the "Senkou Span B" line
    """
    closing_prices = getClosingPrices(coin_pair, 52, unit)
    period_high = max(closing_prices)
    period_low = min(closing_prices)
    return (period_high + period_low) / 2

def findBreakout(coin_pair, period, unit):
    """
    Finds breakout based on how close the High was to Closing and Low to Opening
    """
    hit = 0
    historical_data = my_bittrex.getHistoricalData(coin_pair, period, unit)
    for i in historical_data:
        if (i['C'] == i['H']) and (i['O'] == i['L']):
            hit += 1

    if (hit / period) >= .75:
        message = client.api.account.messages.create(to=secrets['my_number'],from_=secrets['twilio_number'],body="{} is breaking out!".format(coin_pair))
        return "Breaking out!"
    else:
        return "#Bagholding"

def webhookCallback(response):
    print(response.code)
    print(response.body)

# if __name__ == "__main__":
def loop_script():
    for i in coin_pairs:
        breakout = findBreakout(coin_pair=i, period=5, unit="fiveMin")
        sma = calculateSMA(coin_pair=i, period=5, unit="fiveMin")
        ema = calculateEMA(coin_pair=i, period=5, unit="fiveMin")
        rsi = calculateRSI(coin_pair=i, period=14, unit="thirtyMin")
        baseLine = calculateBaseLine(coin_pair=i, unit="day")
        conversionLine = calculateConversionLine(coin_pair=i, unit="day")
        leadSpanA = calculateLeadingSpanA(coin_pair=i, unit="day")
        leadSpanB = calculateLeadingSpanB(coin_pair=i, unit="day")
        closingPrices = getClosingPrices(coin_pair=i, period=14, unit='thirtyMin')
        rangeClosingPrices = getRangeClosingPrices(coin_pair=i, period_from=1, period_to=14, unit='thirtyMin')

        print("{} ======================".format(i))
        print("Breakout: {}".format(breakout))
        print("RSI: {}".format(rsi))
        print("SMA: {}".format(sma))
        print("EMA: {}".format(ema))
        print("Ichimoku: BaseLine: {} ConversionLine: {} LeadSpanA: {} LeadSpanB: {}".format(baseLine, conversionLine, leadSpanA, leadSpanB))
        print("Closing Price: {}".format(map(str, closingPrices)))
        print("Closing Price: {}".format(map(str, rangeClosingPrices)))
        if (rsi >= 55.0 or rsi <= 45.0):
            # unirest.post("https://coinwatch-demo.herokuapp.com/alert", params={
            #     "type": "RSI",
            #     "value": rsi,
            #     "pair": i,
            # }, callback=webhookCallback)
            print("PERFORM POST")
            type = "sell" if rsi >= 55.0 else "buy"
            current_price = my_bittrex.get_ticker(i)
            unirest.post(os.getenv("TRADE_POST_URL"), params={
                "trade": {
                    "transaction_type": type,
                    "pair": i,
                    "amount_ratio": 0.1,
                    "current_price": {
                        "bid": current_price['result']['Bid'],
                        "ask": current_price['result']['Ask']
                    },
                    "bittrex_key": os.getenv("ENCRYPTED_BITTREX_KEY"),
                    "bittrex_secret": os.getenv("ENCRYPTED_BITTREX_SECRET"),
                    "limit_order": False, # TODO: set True to live trade on Bittrex
                    "comment": "Sample Text"
                }
            }, auth=(os.getenv("USER_EMAIL"), os.getenv("USER_PASSWORD")))
        else:
            print("No Webhook")
