from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.urls import reverse
from mygame.forms import *
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
from django.shortcuts import redirect
import time

from mygame.backend.engineeringmodel import EngineeringModel
from .backend.game import Game
from .backend.timer import Timer
from .backend.company import Company
from .backend.worker import Worker
from .backend.order import Order
from .backend.action import Action
from .backend.game import Game
from .backend.engineeringmodel import EngineeringModel
from .backend.event import Event, SpecialOrder


def loginView(request):
    if request.method == "POST":
        try:
            form = LoginForm(request.POST)
            if form.is_valid():
                username = form.cleaned_data["username"]
                gameid = form.cleaned_data["game_id"]
                password = form.cleaned_data["password"]
                choice = form.cleaned_data["create_join_game"]

                # Create oder Join angewählt?
                if choice == "1":
                    lobby = Game.objects.get(id=int(gameid))

                else:
                    timer = Timer.objects.create()
                    lobby, created = Game.objects.get_or_create(
                        name=username + "'s Game", gamemaster=username
                    )
                    lobby.timer = timer
                    lobby.save()
                    gameid = lobby.id

                # Checken ob username existiert:
                # Wenn Ja und passwort stimmt -> einloggen
                # Wenn Ja und passwort flasch -> Fehler
                # Wenn nein -> username mit passwort erstellen
                if User.objects.filter(username=username).exists():
                    user = authenticate(username=username, password=password)
                    if user is not None:
                        login(request, user)

                    else:
                        raise NameError("Username already exists!")

                else:
                    user = User.objects.create_user(
                        username=username, password=password
                    )
                    login(request, user)

                company, created = Company.objects.get_or_create(
                    name=username, user=username
                )
                lobby.participants.add(company)
                lobby.save()

        except:
            error_message = "FEHLER AUFGETRETEN"
        else:
            return HttpResponseRedirect(
                reverse(
                    "lobby",
                    args=(
                        gameid,
                        username,
                    ),
                )
            )
        return render(
            request,
            "mygame/login.html",
            {
                "error_message": error_message,
                "form": form,
            },
        )
    else:
        form = LoginForm()
        return render(request, "mygame/login.html", {"form": form})


def lobby(request, gameid, username):
    game = get_object_or_404(Game, id=gameid)

    if request.method == "POST":
        if request.POST.get("action", False) == "clearlobby":
            game.clearParticipants(username)
        if request.POST.get("action", False) == "changesettings":
            gamesettingsform = GamesettingsForm(
                request.POST,
                initial={
                    "timer": game.timer.timer,
                    "rounds": game.maxRounds,
                    "ordermarketsize": game.ordermarketsize,
                },
            )
            try:
                if gamesettingsform.is_valid():
                    game.maxRounds = gamesettingsform.cleaned_data["rounds"]
                    game.ordermarketsize = gamesettingsform.cleaned_data[
                        "ordermarketsize"
                    ]
                    game.timer.timer = gamesettingsform.cleaned_data["timer"]
                    game.timer.remainingtimer = gamesettingsform.cleaned_data["timer"]
                    game.save()
                    game.timer.save()
            except (KeyError, game.DoesNotExist):
                return render(
                    request,
                    "mygame/lobby.html",
                    {
                        "lobby": game,
                        "gamesettingsform": gamesettingsform,
                        "error_message": "EIN FEHLER IST AUFGETRETEN.",
                    },
                )
                # hier errormessages je nach fehler ausgeben
            else:
                return HttpResponseRedirect(
                    reverse(
                        "lobby",
                        args=(
                            gameid,
                            username,
                        ),
                    )
                )

    gamesettingsform = GamesettingsForm(
        initial={
            "timer": game.timer.timer,
            "rounds": game.maxRounds,
            "ordermarketsize": game.ordermarketsize,
        }
    )

    return render(
        request,
        "mygame/lobby.html",
        {"game": game, "gamesettingsform": gamesettingsform},
    )


def gamerules(request, gameid):
    game = get_object_or_404(Game, id=gameid)
    return render(
        request,
        "mygame/gamerules.html",
        {
            "game": game,
        },
    )


def startGame(request, gameid, username):
    game = get_object_or_404(Game, id=gameid)
    game.startGame()
    return redirect("company", gameid=gameid, username=username)


def company(request, gameid, username):
    game = get_object_or_404(Game, id=gameid)
    company = get_object_or_404(Company, user=username)
    if request.method == "POST":
        if request.POST["action"] == "next round":
            gameend = game.processGameround()
            if gameend:
                return redirect("standings", gameid=gameid, username=username)
            else:
                eventtuple = company.getEvent(0, "default")
                companyevent = eventtuple[0]
                eventnumber = eventtuple[1]
                return render(
                    request,
                    "mygame/email.html",
                    {
                        "game": game,
                        "company": company,
                        "companyevent": companyevent,
                        "eventnumber": eventnumber,
                    },
                )
    return render(request, "mygame/company.html", {"game": game, "company": company})


def companyWorker(request, gameid, username, workerid):
    game = get_object_or_404(Game, id=gameid)
    company = get_object_or_404(Company, user=username)
    try:
        viewedworker = Worker.objects.get(id=workerid)
    except:
        return render(
            request,
            "mygame/company.html",
            {"game": game, "company": company},
        )
    if request.method == "POST":
        if request.POST["action"] == "hire":
            viewedaction = company.actionEmploy(viewedworker)
            return render(
                request,
                "mygame/action.html",
                {"game": game, "company": company, "viewedaction": viewedaction},
            )
        elif request.POST["action"] == "fire":
            viewedaction = company.actionUnemploy(viewedworker)
            return render(
                request,
                "mygame/action.html",
                {"game": game, "company": company, "viewedaction": viewedaction},
            )
        elif request.POST["action"] == "train":
            return companyTraining(request, gameid, username, workerid)
    return render(
        request,
        "mygame/worker.html",
        {"game": game, "company": company, "viewedworker": viewedworker},
    )


def companyOrder(request, gameid, username, orderid):
    game = get_object_or_404(Game, id=gameid)
    company = get_object_or_404(Company, user=username)
    try:
        viewedorder = get_object_or_404(Order, id=orderid)
    except:
        return render(
            request,
            "mygame/company.html",
            {"game": game, "company": company},
        )

    if request.method == "POST":
        if request.POST["action"] == "offer":
            try:
                amount = int(request.POST["offerfield"])
                acceptoffer = viewedorder.checkOffer(amount)
                if acceptoffer == False:
                    errormessage = "you can only offer 20 percent higher or lower than the estimated profit"
                    return render(
                        request,
                        "mygame/order.html",
                        {
                            "game": game,
                            "company": company,
                            "viewedorder": viewedorder,
                            "errormessage": errormessage,
                        },
                    )
            except:
                errormessage = "please enter numbers only"
                return render(
                    request,
                    "mygame/order.html",
                    {
                        "game": game,
                        "company": company,
                        "viewedorder": viewedorder,
                        "errormessage": errormessage,
                    },
                )
            else:
                viewedaction = company.actionOffer(order=viewedorder, amount=amount)
                return render(
                    request,
                    "mygame/action.html",
                    {"game": game, "company": company, "viewedaction": viewedaction},
                )
        if request.POST["action"] == "assign resources":
            return render(
                request,
                "mygame/assign.html",
                {"game": game, "company": company, "assignorder": viewedorder},
            )
        if request.POST["action"] == "cancel":
            viewedaction = company.actionCancelOrder(viewedorder)
            return render(
                request,
                "mygame/action.html",
                {"game": game, "company": company, "viewedaction": viewedaction},
            )
        if request.POST["action"] == "save assignment":
            for worker in company.workers.all():
                workerid = request.POST.get("assign " + str(worker.id), 0)
                if workerid != 0:
                    viewedorder.assignWorker(worker)
                    viewedorder.save()
                workerid = request.POST.get("unassign " + str(worker.id), 0)
                if workerid != 0:
                    viewedorder.unassignWorker(worker)
                    viewedorder.save()

            return render(
                request,
                "mygame/assign.html",
                {"game": game, "company": company, "assignorder": viewedorder},
            )

    return render(
        request,
        "mygame/order.html",
        {"game": game, "company": company, "viewedorder": viewedorder},
    )


def companyTraining(request, gameid, username, workerid):
    game = get_object_or_404(Game, id=gameid)
    company = get_object_or_404(Company, user=username)
    try:
        trainworker = get_object_or_404(Worker, id=workerid)
    except:
        return render(
            request,
            "mygame/company.html",
            {"game": game, "company": company},
        )

    if request.method == "POST":
        trainskill = request.POST.get("trainskill", False)
        if trainskill:
            viewedaction = company.actionTrain(
                worker=trainworker, trainskill=trainskill
            )
            return render(
                request,
                "mygame/action.html",
                {"game": game, "company": company, "viewedaction": viewedaction},
            )

    return render(
        request,
        "mygame/training.html",
        {"game": game, "company": company, "trainworker": trainworker},
    )


def companyAction(request, gameid, username, actionid):
    game = get_object_or_404(Game, id=gameid)
    company = get_object_or_404(Company, user=username)
    # hier schauen welche action es ist dann aus entsprechender table holen
    try:
        viewedaction = get_object_or_404(Action, id=actionid)
    except:
        return render(
            request,
            "mygame/company.html",
            {"game": game, "company": company},
        )

    if request.method == "POST":
        if request.POST["action"] == "cancel":
            company.cancelAction(id=actionid)
            return render(
                request,
                "mygame/company.html",
                {"game": game, "company": company},
            )

    return render(
        request,
        "mygame/action.html",
        {"game": game, "company": company, "viewedaction": viewedaction},
    )


def companyEvent(request, gameid, username, eventnumber):
    game = get_object_or_404(Game, id=gameid)
    company = get_object_or_404(Company, user=username)

    if request.method == "POST":
        if request.POST.get("action", False) == "previous":
            eventresult = company.getEvent(eventnumber, "previous")
        if request.POST.get("action", False) == "next":
            eventresult = company.getEvent(eventnumber, "next")
    else:
        eventresult = company.getEvent(eventnumber, "default")

    companyevent = eventresult[0]
    eventnumber = eventresult[1]

    return render(
        request,
        "mygame/email.html",
        {
            "game": game,
            "company": company,
            "companyevent": companyevent,
            "eventnumber": eventnumber,
        },
    )


def companyEventSetModel(request, gameid, username, eventid, modelnumber):
    game = get_object_or_404(Game, id=gameid)
    company = get_object_or_404(Company, user=username)
    engineeringmodels = EngineeringModel.objects.all()

    if request.method == "POST":
        if request.POST.get("action", False) == "previous":
            modelnumber -= 1
            if modelnumber < 0:
                modelnumber = engineeringmodels.count() - 1
            engineeringmodel = engineeringmodels[modelnumber]
        if request.POST.get("action", False) == "next":
            modelnumber += 1
            if modelnumber > (engineeringmodels.count() - 1):
                modelnumber = 0
        if request.POST.get("action", False) == "set model":
            eventofferaccepted = Event.objects.get(id=eventid)
            setmodel = engineeringmodels.order_by("id")[modelnumber]
            eventofferaccepted.setModel(setmodel)
            return render(
                request,
                "mygame/email.html",
                {
                    "game": game,
                    "company": company,
                    "companyevent": eventofferaccepted,
                    "eventnumber": 0,
                },
            )

    engineeringmodel = engineeringmodels.order_by("id")[modelnumber]

    return render(
        request,
        "mygame/engineeringmodel.html",
        {
            "game": game,
            "company": company,
            "engineeringmodel": engineeringmodel,
            "modelnumber": modelnumber,
            "eventid": eventid,
        },
    )


def companySpecialOrder(request, gameid, username, specialorderid):
    game = get_object_or_404(Game, id=gameid)
    company = get_object_or_404(Company, user=username)
    if request.method == "POST":
        specialorder = SpecialOrder.objects.get(id=specialorderid)
        for order in company.orders.all():
            if order.specialorder.id == specialorderid:
                order = order
        if request.POST.get("action", False) == "handle":
            event = specialorder.handle(order=order, company=company, handle=True)

        if request.POST.get("action", False) == "ignore":
            event = specialorder.handle(order=order, company=company, handle=False)

    return render(
        request,
        "mygame/email.html",
        {"game": game, "company": company, "companyevent": event, "eventnumber": 0},
    )


def standings(request, gameid, username):
    game = get_object_or_404(Game, id=gameid)
    company = get_object_or_404(Company, user=username)
    leaderboard = game.createLeaderboard()
    return render(
        request,
        "mygame/standings.html",
        {"game": game, "company": company, "leaderboard": leaderboard},
    )
