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

import android.content.Context;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

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

public class Modules implements Iterable<Modules.Module>, Serializable {
    private SortedListModule list;
    private final LoginToken token;
    //private transient Logger log = new Logger(this);
    private static final String FILE_NAME = "ModuleListSaving";

    public Modules(LoginToken loginToken) {
        this.token = loginToken;
        this.list = new SortedListModule();
    }

    public void addModule(String semester, HashSet<String> lvNumber, String title, HashSet<Lecturer> lecturer, String type, String description, String ID) {
        Module m = new Module(semester, lvNumber, title, lecturer, type, description, ID);
        this.list.add(m);
    }

    @Override
    public String toString() {
        return this.list.toString();
    }

    @NonNull
    @Override
    public Iterator<Module> iterator() {
        return this.list.iterator();
    }

    public Iterator<Module> latestSemesterIterator() {
        return this.list.filteredIterator(this.list.getLatestSemester());
    }

    public int size() {
        return this.list.size();
    }

    public Module get(String id) {
        return this.list.getById(id);
    }

    public Module getByIndex(int index) {
        return this.list.get(index);
    }

    public static Modules load(Context context) throws IOException, ClassNotFoundException {
        FileInputStream fis = context.openFileInput(FILE_NAME);
        ObjectInputStream is = new ObjectInputStream(fis);
        Modules modules = (Modules) is.readObject();
        is.close();
        fis.close();
        return modules;
    }

    public void save(Context context) throws IOException {
        FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
        ObjectOutputStream os = new ObjectOutputStream(fos);
        os.writeObject(this);
        os.close();
        fos.close();
    }

    public void delete(Context context) {
        context.deleteFile(FILE_NAME);
    }

    public LoginToken getToken() {
        return token;
    }

    public void updateList(Modules modules) {
        SortedListModule old = this.list;
        this.list = modules.list;
        for (Module oldModule : old) {
            Module newModule = this.list.getById(oldModule.getID());
            if (newModule != null) {
                newModule.announcements = oldModule.announcements;
                newModule.assignments = oldModule.assignments;
                newModule.events = oldModule.events;
                newModule.gradebook = oldModule.gradebook;
                newModule.resources = oldModule.resources;
            }
        }
    }

    public class Module implements Serializable {
        public final String semester;
        final HashSet<String> lvNumber;
        public final String title;
        final HashSet<Lecturer> lecturer;
        public final String type;
        public final String description;
        private final String ID;
        @Nullable public ArrayList<Announcement> announcements;
        @Nullable public AssignmentList assignments;
        @Nullable public EventList events;
        @Nullable public ArrayList<Gradebook> gradebook;
        @Nullable public ArrayList<Resource> resources;

        /*private Module() {
            this(null, null, null, null, null);
            throw new AssertionError("Do not use this constructor!");
        }*/

        public float getGradebookPercent(){
            float maxPoint = 0;
            float userPoint = 0;
            if (gradebook != null) {
                for (Gradebook g : gradebook){
                    maxPoint += g.getMaxPoints();
                    userPoint += g.getPoints();
                }
            }
            if (maxPoint == 0)
                return 0;
            return userPoint/maxPoint;
        }

        private Module(String semester, HashSet<String> lvNumber, String title, HashSet<Lecturer> lecturer, String type, String description, String ID) {
            semester = semester.replace("SS", "S");
            semester = semester.replaceAll("[0-9]{2}([0-9]{2})", "$1");
            title = title.replaceAll("(.*?) (S[0-9]{2}|W[0-9/]{5})", "$1");

            this.semester = semester;
            this.lvNumber = lvNumber;
            this.title = title;
            this.lecturer = lecturer;
            this.type = type;
            this.description = description;
            this.ID = ID;
        }

        public String getID() {
            return ID;
        }

        @Override
        public String toString() {
            return "Semester: "+semester+
                    "\nlvNumber: "+lvNumber.toString()+
                    "\ntitle: "+title+
                    "\nlecturer: "+lecturer.toString()+
                    "\ntype: "+type+
                    "\nID: "+ID;
        }
    }
}
