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 LoginTokenBB {
    private final String s_session_id;
    private final String session_id;
    private final String username;
    private boolean isAvailable = true;
    @Nullable private String id;
    @Nullable private String studentId;

    public LoginTokenBB(String username, String s_session_id, String session_id) {
        this.username = username;
        this.s_session_id = s_session_id;
        this.session_id = session_id;
    }

    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_BLACKBOARD, tokenString -> {
            if (tokenString == null) {
                callback.run(null);
                return;
            }
            callback.run(LoginTokenBB.fromJsonString(tokenString));
        }, errorCallback);
    }

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

    public void setAdditionals(String id, String studentId) {
        this.id = id;
        this.studentId = studentId;
        this.isAvailable = true;
    }

    public void setNotAvailable() {
        this.id = null;
        this.studentId = null;
        this.isAvailable = false;
    }

    public boolean isAvailable() {
        return isAvailable;
    }

    public String getUsername() {
        return username;
    }

    private String getSessionId() {
        return session_id;
    }

    public String getSSessionId() {
        return s_session_id;
    }

    @Nullable
    public String getId() {
        return id;
    }

    @Nullable
    public String getStudentId() {
        return studentId;
    }

    public HashMap<String, String> getCookies() {
        HashMap<String, String> cookies = new HashMap<>();
        cookies.put("session_id", getSessionId());
        cookies.put("s_session_id", getSSessionId());
        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("s_session_id", s_session_id);
            json.put("session_id", session_id);
            json.put("username", username);
            json.put("id", id);
            json.put("studentId", studentId);
            json.put("isAvailable", isAvailable);
        } catch (JSONException e) {
            return null;
        }
        return json.toString();
    }

    private static LoginTokenBB fromJsonString(String tokenString) {
        try {
            JSONObject json = new JSONObject(tokenString);
            LoginTokenBB token = new LoginTokenBB(
                    json.getString("username"),
                    json.getString("s_session_id"),
                    json.getString("session_id"));
            if (!json.isNull("id"))
                token.setAdditionals(
                        json.getString("id"),
                        json.getString("studentId")
                );
            if (!json.optBoolean("isAvailable", true)) {
                token.setNotAvailable();
            }
            return token;
        } catch (JSONException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(s_session_id, session_id, username, id, studentId);
    }

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