#!/usr/bin/python
# -*- coding: utf-8 -*-
import datetime
import json

import requests
from dateutil.relativedelta import relativedelta

from homevee.Helper import Logger
from homevee.Helper.helper_functions import load_remote_data
from homevee.items.Status import *


def get_nutrition_data(username, keyword, db):
    data = {'action': 'findsingleitem', 'term': keyword}

    Logger.log("Nutrition item search: "+keyword)

    r = requests.post("https://food.homevee.de/api.php", data=data)
    # Logger.log(r.status_code, r.reason)

    if (r.status_code != 200):
        return None

    response = r.text

    #print response

    data = json.loads(response)

    if(data is None):
        return None

    if('food' not in data):
        return None

    nutrition_data = data['food']

    if(nutrition_data is None):
        return None

    if(len(nutrition_data) is 0):
        return False

    return nutrition_data[0]

def submit_food(username, name, calories, portionsize, portionunit, protein, fat, saturated, unsaturated, carbs, sugar, ean, db):
    remote_data = load_remote_data(username, db)
    remote_id = remote_data['remote_id']

    if(remote_id is None or remote_id == ""):
        return {'result': 'noremoteid'}

    data = {'action': 'submitfood', 'name': name, 'calories': calories, 'portionsize': portionsize, 'portionunit': portionunit,
            'protein': protein, 'fat': fat, 'saturated': saturated, 'unsaturated': unsaturated, 'carbs': carbs,
            'sugar': sugar, 'ean': ean, 'user_remote_id': remote_id}

    r = requests.post("https://food.homevee.de/api.php", data=data)
    #Logger.log(r.status_code, r.reason)

    if(r.status_code != 200):
        return {"result": "error"}

    result = json.loads(r.text)

    if("result" in result):
        if(result['result'] == "ok"):
            return Status(type=STATUS_OK).get_dict()

    return Status(type=STATUS_ERROR).get_dict()

def get_user_day_nutrition_data(username, db):
    with db:
        cur = db.cursor()
    return

def get_user_nutrition_overview(user, db):
    with db:
        cur = db.cursor()

        user_profile = get_user_fitness_profile(user, db)

        Logger.log(user_profile)

        output = {}

        if (user_profile is False):
            has_profile = False
        else:
            has_profile = True

            cur.execute("SELECT * FROM NUTRITION_DATA WHERE USER = :user AND DATE = :date",
                        {'user': user.username, 'date': datetime.datetime.today().strftime("%d.%m.%Y")})

            eaten_calories_today = 0
            eaten_fat_today = 0
            eaten_carbs_today = 0
            eaten_protein_today = 0

            for item in cur.fetchall():

                amount = (float(item['EATEN_PORTION_SIZE'])/float(item['PORTIONSIZE']))

                eaten_calories_today += item['CALORIES']*amount
                eaten_fat_today += item['FAT']*amount
                eaten_carbs_today += item['CARBS']*amount
                eaten_protein_today += item['PROTEIN']*amount

            #print datetime.datetime.today().strftime("%Y-%m-%d")

            nutrition_distribution = {'fat': eaten_fat_today, 'carbs': eaten_carbs_today,
                                      'protein': eaten_protein_today}
            nutrition_day_data = {'calories_goal': int(user_profile['caloriesgoal']), 'calories_left': int(user_profile['caloriesgoal']-eaten_calories_today), 'nutrition_distribution': nutrition_distribution}

            output['nutrition_day_data'] = nutrition_day_data

        weight_progress = {}

        output['has_profile'] = has_profile
        output['weight_progress'] = weight_progress

        return {'data': output}

def save_user_settings(username, height, weight, birthdate, mode, activity, db):
    calories_goal = get_calorie_need(birthdate, weight, height, activity, mode)

    protein_goal, carbs_goal, fat_goal = get_macro_distribution(calories_goal)

    water_goal = 2.0

    add_user_weight(username, weight, db)

    with db:
        cur = db.cursor()

        cur.execute("SELECT COUNT(*) FROM USER_FITNESS_DATA WHERE USERNAME = :user", {'user': username})

        result = cur.fetchone()['COUNT(*)']

        param_array = {'cals': calories_goal, 'user': username, 'fat': fat_goal, 'saturated': 0, 'carbs': carbs_goal,
                       'sugar': 0, 'protein': protein_goal, 'water': water_goal, 'birthdate': birthdate, 'height': height,
                       'weight': weight, 'activity':activity, 'diet': mode}

        if(result == 0):
            cur.execute("INSERT INTO USER_FITNESS_DATA (USERNAME, CALORIE_GOAL, FAT_GOAL, SATURATED_GOAL, CARBS_GOAL, SUGAR_GOAL, PROTEIN_GOAL, WATER_GOAL, BIRTHDATE, HEIGHT, ACTIVITY_MODE, DIET_MODE) VALUES (:user, :cals, :fat, :saturated, :carbs, :sugar, :protein, :water, :birthdate, :height, :activity, :diet)", param_array)
        else:
            cur.execute("UPDATE USER_FITNESS_DATA SET CALORIE_GOAL = :cals, FAT_GOAL = :fat, SATURATED_GOAL = :saturated, CARBS_GOAL = :carbs, SUGAR_GOAL = :sugar, PROTEIN_GOAL = :protein, WATER_GOAL = :water, BIRTHDATE = :birthdate, HEIGHT = :height, ACTIVITY_MODE = :activity, DIET_MODE = :diet WHERE USERNAME = :user", param_array)

    return {'result': 'ok', 'calories_goal': calories_goal, 'protein_goal': protein_goal, 'carbs_goal': carbs_goal, 'fat_goal': fat_goal}

def get_macro_distribution(calories):

    protein_factor = 0.25
    carbs_factor = 0.5
    fat_factor = 0.25

    protein_goal = (calories/4)*protein_factor
    carbs_goal = (calories/4)*carbs_factor
    fat_goal = (calories/8)*fat_factor

    return int(protein_goal), int(carbs_goal), int(fat_goal)

def load_user_settings(username, db):
    with db:
        cur = db.cursor()

        data = {}

        #{'sitting': 1.2, 'lightactivity': 1.35, 'moderateactivity': 1.55, 'highactivity': 1.75, 'extremeactivity': 1.95}

        data['activities'] = [
            {'title': 'Sitzend', 'description': 'wenig/kein Training + Bürotätigkeit', 'key': 'sitting'},
            {'title': 'leichte Aktivität', 'description': 'geringe tägliche Aktivität + leichtes Training 1-3 Mal/ Woche', 'key': 'lightactivity'},
            {'title': 'moderate Aktivität', 'description': 'moderate tägliche Aktivität + moderates Training 3-5 Mal/ Woche', 'key': 'moderateactivity'},
            {'title': 'hohe Aktivität', 'description': 'körperlich anspruchsvoller Lifestyle + schweres Training/Sport 6-7 Mal/ Woche', 'key': 'highactivity'},
            {'title': 'extrem hohe Aktivität', 'description': 'hartes tägliches Training/Sport und/oder körperlich beanspruchender Job', 'key': 'extremeactivity'}
        ]

        data['modes'] = [
            {'title': 'stark Abnehmen', 'key': 'harddiet'},
            {'title': 'Abnehmen', 'key': 'diet'},
            {'title': 'Gewicht halten', 'key': 'hold'},
            {'title': 'Muskeln aufbauen', 'key': 'gainmuscles'}
        ]

        cur.execute("SELECT * FROM USER_WEIGHT_DATA WHERE USERNAME = :user ORDER BY DATE DESC", {'user': username})
        weight_data = cur.fetchone()['WEIGHT']

        cur.execute("SELECT * FROM USER_FITNESS_DATA WHERE USERNAME = :user", {'user': username})
        result = cur.fetchone()

        activity_title = None
        for item in data['activities']:
            if(item['key'] == result['ACTIVITY_MODE']):
                activity_title = item['title']
                break

        mode_title = None
        for item in data['modes']:
            if(item['key'] == result['DIET_MODE']):
                mode_title = item['title']
                break

        settings = {'weight': weight_data, 'height': result['HEIGHT'], 'birthdate': result['BIRTHDATE'],'activity': result['ACTIVITY_MODE'],
                    'activity_title': activity_title, 'mode': result['DIET_MODE'], 'mode_title': mode_title}

        data['settings'] = settings

        return {'data': data}

def add_user_weight(username, weight, db):
    with db:
        cur = db.cursor()

        date = datetime.datetime.today().__format__("%Y-%m-%d")

        cur.execute("INSERT INTO USER_WEIGHT_DATA (USERNAME, DATE, WEIGHT) VALUES (:user, :date, :weight)",
                   {'user':username, 'date': date, 'weight': weight})

def delete_food_item(username, id, db):
    with db:
        cur = db.cursor()

        cur.execute("DELETE FROM NUTRITION_DATA WHERE ID = :id AND USER = :user",
                    {'id': id, 'user': username})

        return Status(type=STATUS_OK).get_dict()

def get_calorie_need(birthdate, weight, height, movement_mode, diet_mode):
    # (9.99 x Körpergewicht (in kg)) + (6.25 x Körpergröße (in cm)) – (4.92 x Alter (in Jahren)) – 161

    birthdate = datetime.datetime.strptime(birthdate, "%Y-%m-%d")
    today = datetime.datetime.today()
    age = relativedelta(today, birthdate).years

    base_calories = (9.99 * int(weight)) + (6.25 * int(height)) - (4.92 * age) - 161

    movement_factor = 1.2
    movement_map = {'sitting': 1.2, 'lightactivity': 1.35, 'moderateactivity': 1.55, 'highactivity': 1.75, 'extremeactivity': 1.95}
    if(movement_mode in movement_map):
        movement_factor = movement_map[movement_mode]
    calories_with_movement = base_calories * movement_factor

    diet_factor = 1
    diet_map = {'harddiet': 0.8, 'diet': 0.9, 'hold': 1.0, 'musclegain': 1.1}
    if(diet_mode in diet_map):
        diet_factor = diet_map[diet_mode]
    Logger.log(diet_mode)
    diet_calories = calories_with_movement * diet_factor

    calories_needed = diet_calories

    return int(calories_needed)

def get_user_fitness_profile(user, db):
    with db:
        cur = db.cursor()

        cur.execute("SELECT * FROM USER_FITNESS_DATA WHERE USERNAME = :user", {'user': user.username})

        result = cur.fetchone()

        if(result is None):
            return False

        data = {'caloriesgoal': result['CALORIE_GOAL'], 'fatgoal': result['FAT_GOAL'], 'saturatedgoal': result['SATURATED_GOAL'],
                'carbsgoal': result['CARBS_GOAL'], 'sugargoal': result['SUGAR_GOAL'], 'proteingoal': result['PROTEIN_GOAL'],
                'watergoal': result['WATER_GOAL']}

        return data

def get_user_weight_progress(username, start, end, db):
    start = datetime.datetime.strptime(start, "%d.%m.%Y").strftime("%Y-%m-%d")
    end = datetime.datetime.strptime(end, "%d.%m.%Y").strftime("%Y-%m-%d")

    with db:
        cur = db.cursor()

        weight_items = []

        cur.execute("SELECT WEIGHT, strftime(\"%d.%m.%Y\", DATE) as DATETIME FROM USER_WEIGHT_DATA WHERE USERNAME = :user AND DATE >= :start AND DATE <= :ende ORDER BY DATE ASC",
                    {'user': username, 'start': start, 'end': end})

        for item in cur.fetchall():
            weight_items.append({'date': item['DATETIME'], 'weight': item['WEIGHT']})

        return {'progress': weight_items}

def get_user_day_nutrition_items(username, date, db):
    with db:
        cur = db.cursor()

        daytime_items = {'morning': [], "noon": [], "evening": [], "snacks": []}

        cur.execute("SELECT * FROM NUTRITION_DATA WHERE USER = :user AND DATE = :date",
                    {'user': username, 'date': date})

        for item in cur.fetchall():
            food_item = {'id': item['ID'], 'daytime': item['DAYTIME'], 'name': item['FOOD_NAME'], 'eatenportionsize': item['EATEN_PORTION_SIZE'],
                         'portionsize': item['PORTIONSIZE'], 'portionunit': item['PORTIONUNIT'], 'calories': item['CALORIES'],
                         'fat': item['FAT'], 'saturated': item['SATURATED'], 'unsaturated': item['UNSATURATED'],
                         'carbs': item['CARBS'], 'sugar': item['SUGAR'], 'protein': item['PROTEIN'], 'date': item['DATE']}

            if(item['DAYTIME'] in daytime_items):
                daytime_items[item['DAYTIME']].append(food_item)
            else:
                daytime_items['snacks'].append(food_item)

        calories_goal = get_user_fitness_profile(username, db)['caloriesgoal']

        return {'items': daytime_items, 'caloriesgoal': calories_goal}

def move_item(username, id, date, daytime, deleteold, db):
    with db:
        cur = db.cursor()

        cur.execute("SELECT * FROM NUTRITION_DATA WHERE ID = :id", {'id': id})
        item = cur.fetchone()

        if(item is None):
            return {'result': 'itemnotexisting'}

        name = item['FOOD_NAME']
        eatenportionsize = item['EATEN_PORTION_SIZE']
        portionsize = item['PORTIONSIZE']
        portionunit = item['PORTIONUNIT']
        calories = item['CALORIES']
        fat = item['FAT']
        saturated = item['SATURATED']
        unsaturated = item['UNSATURATED']
        carbs = item['CARBS']
        sugar = item['SUGAR']
        protein = item['PROTEIN']

        add_edit_user_day_nutrition_item(username, None, date, daytime, name, eatenportionsize, portionsize, portionunit,
                                         calories, fat, saturated, unsaturated, carbs, sugar, protein, db)

        if deleteold == "true" or deleteold == True or deleteold == 1 or deleteold == "1":
            cur.execute("DELETE FROM NUTRITION_DATA WHERE ID = :id", {'id': id})

    return Status(type=STATUS_OK).get_dict()

def add_edit_user_day_nutrition_item(username, id, date, daytime, name, eatenportionsize, portionsize, portionunit, calories, fat, saturated, unsaturated, carbs, sugar, protein, db):
    add_new = (id == None or id == "" or id == "-1")

    with db:
        cur = db.cursor()

        param_array = {'user': username, 'date': date, 'daytime': daytime, 'name': name, 'eatenportionsize': eatenportionsize,
                       'portionsize': portionsize, 'portionunit': portionunit, 'calories': calories, 'fat': fat,
                       'saturated': saturated, 'unsaturated': unsaturated, 'carbs': carbs, 'sugar': sugar, 'protein': protein}

        if add_new:
            cur.execute("INSERT INTO NUTRITION_DATA (USER, DATE, DAYTIME, FOOD_NAME, EATEN_PORTION_SIZE, PORTIONSIZE, PORTIONUNIT, CALORIES, FAT, SATURATED, UNSATURATED, CARBS, SUGAR, PROTEIN) VALUES (:user, :date, :daytime, :name, :eatenportionsize, :portionsize, :portionunit, :calories, :fat, :saturated, :unsaturated, :carbs, :sugar, :protein)",
                        param_array)
        else:
            param_array['id'] = id

            cur.execute("UPDATE NUTRITION_DATA SET USER = :user, DATE = :date, DAYTIME = :daytime, FOOD_NAME = :name, EATEN_PORTION_SIZE = :eatenportionsize, PORTIONSIZE = :portionsize, PORTIONUNIT = :portionunit, CALORIES = :calories, FAT = :fat, SATURATED = :saturated, UNSATURATED = :unsaturated, CARBS = :carbs, SUGAR = :sugar, PROTEIN = :protein WHERE ID = :id",
                        param_array)

    return Status(type=STATUS_OK).get_dict()