package de.sebse.fuplanner.services.kvv.types;

import com.google.android.gms.common.internal.Objects;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import de.sebse.fuplanner.services.fulogin.AccountGeneral;
import de.sebse.fuplanner.tools.CustomAccountManager;

/**
 * Created by sebastian on 29.10.17.
 */

public class LoginTokenKVV {
    private final String username;
    private final String JSESSIONID;
    private boolean isAvailable = true;
    @Nullable private String fullName;
    @Nullable private String email;

    public LoginTokenKVV(String username, String JSESSIONID) {
        this.username = username;
        this.JSESSIONID = JSESSIONID;
    }

    public static void load(CustomAccountManager manager, LoginTokenInterface callback, CustomAccountManager.ExceptionInterface errorCallback) {
        if (!manager.hasAccounts(AccountGeneral.ACCOUNT_TYPE)) {
            callback.run(null);
            return;
        }
        manager.getTokenByType(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV, tokenString -> {
            if (tokenString == null) {
                callback.run(null);
                return;
            }
            callback.run(LoginTokenKVV.fromJsonString(tokenString));
        }, errorCallback);
    }

    public void delete(CustomAccountManager manager) {
        manager.deleteAccount(AccountGeneral.ACCOUNT_TYPE);
    }

    public void setAdditionals(String fullName, String email) {
        this.fullName = fullName;
        this.email = email;
        this.isAvailable = true;
    }

    public void setNotAvailable() {
        this.fullName = null;
        this.email = null;
        this.isAvailable = false;
    }

    public boolean isAvailable() {
        return isAvailable;
    }

    public String getUsername() {
        return username;
    }

    private String getJSESSIONID() {
        return JSESSIONID;
    }

    @Nullable
    public String getFullName() {
        return fullName;
    }

    @Nullable
    public String getEmail() {
        return email;
    }

    public HashMap<String, String> getCookies() {
        HashMap<String, String> cookies = new HashMap<>();
        cookies.put("JSESSIONID", getJSESSIONID());
        cookies.put("pasystem_timezone_ok", "true");
        return cookies;
    }

    public boolean isOtherUser(String username) {
        return !this.getUsername().equals(username);
    }

    @NonNull
    @Override
    public String toString() {
        StringBuilder result = new StringBuilder();
        HashMap<String, String> cookies = this.getCookies();
        for (String header: cookies.keySet()) {
            result.append(header).append("=").append(cookies.get(header)).append(";");
        }
        return result.substring(0, result.length()-1);
    }

    public String toJsonString() {
        JSONObject json = new JSONObject();
        try {
            json.put("username", username);
            json.put("JSESSIONID", JSESSIONID);
            json.put("fullName", fullName);
            json.put("email", email);
            json.put("isAvailable", isAvailable);
        } catch (JSONException e) {
            return null;
        }
        return json.toString();
    }

    private static LoginTokenKVV fromJsonString(String tokenString) {
        try {
            JSONObject json = new JSONObject(tokenString);
            LoginTokenKVV token = new LoginTokenKVV(
                    json.getString("username"),
                    json.getString("JSESSIONID"));
            if (!json.isNull("fullName"))
                token.setAdditionals(
                        json.getString("fullName"),
                        json.getString("email")
                );
            if (!json.optBoolean("isAvailable", true)) {
                token.setNotAvailable();
            }
            return token;
        } catch (JSONException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(username, JSESSIONID, fullName, email);
    }

    public interface LoginTokenInterface {
        void run(LoginTokenKVV token);
    }
}
