package it.integry.integrywmsnative.core.data_recover;

import android.content.Context;

import com.annimon.stream.Optional;
import com.annimon.stream.Stream;
import com.google.android.gms.common.util.IOUtils;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.inject.Inject;
import javax.inject.Singleton;

import it.integry.integrywmsnative.core.CommonConst;
import it.integry.integrywmsnative.core.model.MtbColt;
import it.integry.integrywmsnative.core.rest.model.OrdineUscitaInevasoDTO;

@Singleton
public class ColliDataRecoverService {


    private final Context mApplicationContext;
    private List<ColliDataRecoverDTO> mtbColtsSessions = new ArrayList<>();

    public ColliDataRecoverService(Context applicationContext) {
        this.mApplicationContext = applicationContext;
    }

    @Inject
    public void init() {
        if(isFilePresent(CommonConst.Files.RECOVER_COLLO_FILE)) {
            loadLocalFile();
        }
    }

    public boolean thereIsAnExistantSession() {
        return mtbColtsSessions != null && mtbColtsSessions.size() > 0;
    }

    public List<Integer> getAllSessionIDs() {
        if(thereIsAnExistantSession()) {

            return Stream.of(mtbColtsSessions)
                    .map(ColliDataRecoverDTO::getId)
                    .toList();

        } else return null;
    }

    public ColliDataRecoverDTO getSession(Integer sessionID) {

        if(sessionID == null) return null;

        return getIfExists(sessionID);
    }

    private ColliDataRecoverDTO getIfExists(int id) {
        Optional<ColliDataRecoverDTO> recoverDTOOptional = Stream.of(mtbColtsSessions)
                .filter(x -> x.getId() == id)
                .findSingle();


        return recoverDTOOptional.isPresent() ? recoverDTOOptional.get() : null;
    }

    public int startNewSession(MtbColt mtbColtSession, List<OrdineUscitaInevasoDTO> testateOrdini) {
        Integer newId = null;

        while(newId == null) {
            int randomId = new Random().nextInt(1000);
            ColliDataRecoverDTO dto = getIfExists(randomId);
            if(dto == null) newId = randomId;
        }


        ColliDataRecoverDTO recoverDTO = new ColliDataRecoverDTO()
                .setId(newId)
                .setDataCollo(mtbColtSession.getDataColloS())
                .setNumCollo(mtbColtSession.getNumCollo())
                .setSerCollo(mtbColtSession.getSerCollo())
                .setGestioneCollo(mtbColtSession.getGestione())
                .setFiltro(mtbColtSession.getFiltroOrdini())
                .setTestateOrdini(testateOrdini);

        mtbColtsSessions.add(recoverDTO);
        updateLocalFile();
        return newId;
    }

    public void closeSession(int ID) {
        ColliDataRecoverDTO dto = getIfExists(ID);

        if(dto != null) {
            mtbColtsSessions.remove(dto);
            updateLocalFile();
        }
    }


    private void loadLocalFile() {
        InputStream inputStream;
        Gson gson = new Gson();

        try {
            inputStream = mApplicationContext.openFileInput(CommonConst.Files.RECOVER_COLLO_FILE);

            byte[] bytes = IOUtils.readInputStreamFully(inputStream);
            String jsonString = new String(bytes);

            Type listType = new TypeToken<ArrayList<ColliDataRecoverDTO>>(){}.getType();
            mtbColtsSessions = gson.fromJson(jsonString, listType);

            inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
//            UtilityExceptions.defaultException(mContext, e);
        }
    }


    private void updateLocalFile() {
        FileOutputStream outputStream;

        Gson gson = new Gson();
        String jsonText = gson.toJson(mtbColtsSessions);

        try {
            outputStream = mApplicationContext.openFileOutput(CommonConst.Files.RECOVER_COLLO_FILE, Context.MODE_PRIVATE);
            outputStream.write(jsonText.getBytes());
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
//            UtilityExceptions.defaultException(mContext, e);
        }
    }

    private boolean isFilePresent(String fileName) {
        String path = mApplicationContext.getFilesDir().getAbsolutePath() + "/" + fileName;
        File file = new File(path);
        return file.exists();
    }

}
