package de.sebse.fuplanner.services.kvv;

import android.content.Context;

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

import java.util.ArrayList;

import de.sebse.fuplanner.services.kvv.types.Assignment;
import de.sebse.fuplanner.services.kvv.types.AssignmentList;
import de.sebse.fuplanner.services.kvv.types.Modules;
import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkError;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback;

public class ModulesAssignments extends PartModules<AssignmentList> {

    ModulesAssignments(Login login, ModulesList list, Context context) {
        super(login, list, context);
    }

    @Override
    protected AssignmentList getPart(Modules.Module module) {
        return module.assignments;
    }

    @Override
    protected boolean setPart(Modules.Module module, AssignmentList part) {
        boolean changed = module.assignments == null || module.assignments.hashCode() != part.hashCode();
        module.assignments = part;
        return changed;
    }

    @Override
    protected void upgrade(final String ID, final NetworkCallback<AssignmentList> callback, final NetworkErrorCallback errorCallback) {
        if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) {
            errorCallback.onError(new NetworkError(101304, 500, "Currently running in offline mode!"));
            return;
        }
        get(String.format("https://kvv.imp.fu-berlin.de/direct/assignment/site/%s.json", ID), mLogin.getLoginToken().getCookies(), response -> {
            String body = response.getParsed();
            if (body == null) {
                errorCallback.onError(new NetworkError(101301, 403, "No assignments retrieved!"));
                return;
            }
            AssignmentList assignments = new AssignmentList();
            JSONArray sites;
            try {
                JSONObject json = new JSONObject(body);
                sites = json.getJSONArray("assignment_collection");
            } catch (JSONException e) {
                e.printStackTrace();
                errorCallback.onError(new NetworkError(101302, 403, "Cannot parse assignments!"));
                return;
            }

            for (int i = 0; i < sites.length(); i++) {
                try {
                    JSONObject site = sites.getJSONObject(i);
                    String id = site.getString("id");
                    String title = site.getString("title");
                    String instructions = site.getString("instructions");
                    instructions = String.valueOf(fromHtml(instructions));
                    long dueTime = site.getJSONObject("dueTime").getLong("time");
                    String gradebookItemName = site.optString("gradebookItemName", null);
                    String gradeScale = site.getString("gradeScale");
                    JSONArray attachments = site.getJSONArray("attachments");
                    ArrayList<String> urls = new ArrayList<>();
                    for (int j = 0; j < attachments.length(); j++) {
                        urls.add(attachments.getJSONObject(j).getString("url"));
                    }
                    assignments.add(0, new Assignment(id, title, dueTime, gradebookItemName, gradeScale, urls, instructions));
                } catch (JSONException e) {
                    log.e(new NetworkError(101305, 403, "Cannot parse assignments!"));
                    e.printStackTrace();
                    log.e("ID:", i, "JSON:", sites);
                    return;
                }
            }

            // Empty assignments *may be* because token is invalid -> check
            if (assignments.size() == 0)
                mLogin.testLoginToken(token -> callback.onResponse(assignments), errorCallback);
            else
                callback.onResponse(assignments);
        }, error -> errorCallback.onError(new NetworkError(101303, error.networkResponse.statusCode, "Cannot get assignments!")));
    }
}
