package com.bernard.mcqinator.controller;

import android.content.Context;
import android.support.annotation.Nullable;
import android.util.Log;

import com.bernard.mcqinator.api.QuizMetadata;
import com.bernard.mcqinator.api.quiz.Quiz;
import com.bernard.mcqinator.inutil.ArrayInutil;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author samy
 * @date on 23/07/17.
 */

public final class QuizMetadataManager {

    private static List<QuizMetadata> savedQuizs;


    private static final String SAVED_METADATA_FILENAME = "savedQuizz.bernard";

    public static void saveSavedQuizList(Context ctx){
        DataOutputStream dos = null;
        try {
            //LATER implement Bernard API
            dos = new DataOutputStream(ctx.openFileOutput(SAVED_METADATA_FILENAME, Context.MODE_PRIVATE));
            dos.write(FileManager.bernardSignature);
            dos.write(FileManager.appBernardKey);
            dos.writeInt(-1);// Metadata file identifier
            dos.writeInt(savedQuizs.size());

            for (QuizMetadata m : savedQuizs)
                m.write(dos);

            Log.v("QuizMetadataManager","Quiz metadatas saved !");
        } catch (IOException e) {
            Log.e("QuizMetadataManager","Cannot save quiz metadata list",e);
        }finally {
            if(dos != null)
                try {
                    dos.close();
                } catch (IOException e) {
                    Log.e("QuizMetadataManager","Cannot close the QuizMetadataSaver's DataOutputStream",e);
                }
        }
    }

    public static void retieveSavedQuizList(Context ctx) {
        savedQuizs = new ArrayList<>();
        try {
            //LATER implement bernard API
            if(!ArrayInutil.inArray(SAVED_METADATA_FILENAME,ctx.fileList())){
                Log.v("QuizMetadataManager","Cannot find the savedMetadata file , creating one");
                DataOutputStream dos = new DataOutputStream(ctx.openFileOutput(SAVED_METADATA_FILENAME,Context.MODE_PRIVATE));
                dos.write(FileManager.bernardSignature);
                dos.write(FileManager.appBernardKey);
                dos.writeInt(-1);// Metadata file identifier
                dos.writeInt(0);// Stored QuizMetadata count (no metadata stored)
                dos.close();
                Log.v("QuizMetadataManager","New metadata file created !");
            }
            DataInputStream dis = new DataInputStream(ctx.openFileInput(SAVED_METADATA_FILENAME));

            int readBytes;

            byte[] bernardSignature = new byte[2];
            readBytes = dis.read(bernardSignature);
            if (readBytes != 2 || bernardSignature[0] != FileManager.bernardSignature[0] || bernardSignature[1] != FileManager.bernardSignature[1]) {
                dis.close();
                throw new IOException("The QuizMetatatas file has no bernard sign !");
            }

            byte[] bernardType = new byte[2];
            readBytes = dis.read(bernardType);
            if (readBytes != 2 ||bernardType[0] != FileManager.appBernardKey[0] || bernardType[1] != FileManager.appBernardKey[1]) {
                dis.close();
                throw new IOException("The QuizMetatatas file has no app sign !");
            }

            if (dis.readInt() != -1) {
                dis.close();
                throw new IOException("The QuizMetatatas file has no quizmetadata file sign !");
            }

            int quizCount = dis.readInt();

            for (int i = 0; i < quizCount; i++) {
                savedQuizs.add(QuizMetadata.class.newInstance());
                savedQuizs.get(i).read(dis);
            }
            dis.close();
            Log.v("QuizMetadataManager","Successfuly read quiz metadata file");
        } catch (IOException e) {
            Log.e("QuizMetadataManager", "Corrupted QuizMetadata file !",e);
        } catch (InstantiationException e) {
            Log.e("QuizMetadataManager","Cannot read quizmetadata file : cannot instantiate QuizMetadata",e);
        } catch (IllegalAccessException e) {
            Log.e("QuizMetadataManager","Cannot read quizmetadata file : cannot acess QuizMetadata constructor",e);
        }
    }

    //////////// Get ////////////

    public static List<QuizMetadata> getAll(Context ctx){
        if(savedQuizs == null)
            retieveSavedQuizList(ctx);
        return new ArrayList<>(savedQuizs);
    }

    public static List<QuizMetadata> getAllQuiz(Context ctx,boolean editable){
        if(savedQuizs == null)
            retieveSavedQuizList(ctx);
        List<QuizMetadata> toReturn = new ArrayList<>();
        for (QuizMetadata metadata : savedQuizs)
            if(metadata.isEditable() == editable)toReturn.add(metadata);
        return toReturn;
    }

    public static List<QuizMetadata> getAllQuiz(Context ctx,QuizMetadata.Type t){
        if(savedQuizs == null)
            retieveSavedQuizList(ctx);
        List<QuizMetadata> toReturn = new ArrayList<>();
        for (QuizMetadata metadata : savedQuizs)
            if(metadata.getType().equals(t))toReturn.add(metadata);
        return toReturn;
    }

    @Nullable
    public static QuizMetadata getQuiz(Context ctx,long fileID){
        if(savedQuizs == null)
            retieveSavedQuizList(ctx);
        for (QuizMetadata metadata : savedQuizs)
            if(metadata.getFileID() == fileID)return metadata;
        return null;
    }


    //////////// Delete ////////////

    public static boolean delete(QuizMetadata m) {
        for(QuizMetadata meta : savedQuizs)
            if(meta.getFileID() == m.getFileID())
                return savedQuizs.remove(meta);
        return false;
    }


    //////////// Create ////////////

    public static QuizMetadata createQuiz(Context ctx, String name, String author, QuizMetadata.Type type, boolean editable){
        try {
            Quiz q = type.getQuizClass().newInstance();
            q.genDefault();
            QuizMetadata meta = new QuizMetadata(name,author,FileManager.getAvalivableFileID(ctx),type,editable);
            FileManager.saveQuiz(meta,q,ctx);
            savedQuizs.add(meta);
            return meta;
        } catch (InstantiationException e) {
            Log.e("QuizMetadataManager","Error instantiating some class ... do you have all the constructors needed ?",e);
        } catch (IllegalAccessException e) {
            Log.e("QuizMetadataManager","Error instantiating some class ... are the constructors public if they have to be so ?",e);
        }
        throw new IllegalStateException("Cannot create the quiz ... watch earlier in the log for more informations");
    }

    public static QuizMetadata createQuiz(Context ctx,String name, String author, boolean editable, QuizMetadata parent){
        try {
            Quiz parentQuiz = FileManager.getQuiz(parent,ctx);
            QuizMetadata nMetadata = new QuizMetadata(name,author,FileManager.getAvalivableFileID(ctx),parent.getType(),editable);
            FileManager.saveQuiz(nMetadata,parentQuiz,ctx);
            savedQuizs.add(nMetadata);
            return nMetadata;
        } catch (IOException e) {
            Log.e("QuizMetadataManager","IO error when trying to create the quizz",e);
        }
        throw new IllegalStateException("Cannot create the quiz ... watch earlier in the log for more informations");
    }


}
