/*
 * DSBDirect
 * Copyright (C) 2019 Fynn Godau
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * This software is not affiliated with heinekingmedia GmbH, the
 * developer of the DSB platform.
 */

package godau.fynn.dsbdirect;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.ParseException;
import android.net.Uri;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.util.Log;
import com.android.volley.Response;


import java.io.*;
import java.util.Date;

public class FileManager {

    private Context mContext;

    public FileManager(Context context) {
        mContext = context;

        deleteOldFiles();
    }

    public void saveFile(final Table table, final String response) {
        // Write a String to a File
        // Table table is the table that contains response

        new Thread(new Runnable() {
            @Override
            public void run() {
                String filename = getFilename(Uri.parse(table.getUri()), table.getPublishedDate());

                File file = new File(mContext.getFilesDir(), filename);

                try {
                    FileOutputStream outputStream = new FileOutputStream(file);
                    outputStream.write(response.getBytes());
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).run();


    }

    public void saveFile(final Table table, final Bitmap bitmap) {
        // Write a Bitmap to a File

        new Thread(new Runnable() {
            @Override
            public void run() {
                String filename = getFilename(Uri.parse(table.getUri()), table.getPublishedDate());

                File file = new File(mContext.getFilesDir(), filename);

                try {
                    FileOutputStream outputStream = new FileOutputStream(file);
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }).run();
    }

    public @Nullable String readHtmlFile(File file) {
        // Read a String from a File

        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            byte[] bytes = new byte[(int) file.length()];
            fileInputStream.read(bytes);

            return new String(bytes);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public @Nullable Bitmap readBitmapFile(File file) {
        // Read a Bitmap from a File

        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            return BitmapFactory.decodeStream(fileInputStream);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public @Nullable File exists(Uri sourceUri, Date date) {
        // Check whether this specific version of a file has already been downloaded

        File file = new File(mContext.getFilesDir(), getFilename(sourceUri, date));
        if (file.exists()) {
            return file;
        } else {
            return null;
        }
    }


    public File[] listFiles() {
        return mContext.getFilesDir().listFiles();
    }

    private void deleteOldFiles() {
        // Automatically delete old files

        new Thread(new Runnable() {
            @Override
            public void run() {
                String storeDurationString = new Utility(mContext).getSharedPreferences().getString("cache_duration", "604800000");
                try {
                    int storeDuration = Integer.parseInt(storeDurationString);

                    File[] files = mContext.getFilesDir().listFiles();

                    for (File file : files) {
                        long lastModified = file.lastModified();
                        long now = new Date().getTime();
                        long delta = now - lastModified;
                        if (delta > storeDuration) {
                            boolean deleted = file.delete();
                            Log.d("AUTODELETE", "could delete file " + file.getName() + "? " + deleted);
                        }
                    }
                } catch (NumberFormatException e) {
                    // Normal behavior if files shouldn't be deleted
                    // Also prevents crash when someone plays around with the sharedPreferences file
                    Log.d("AUTODELETE", "deletion duration is not a valid int. files not deleted");
                }

            }
        }).start();
    }

    private String getFilename(Uri uri, Date date) {
        return date.getTime() + "-" + uri.getLastPathSegment();
    }

    // WELCOME TO WRAP(PER) ZONE

    public @Nullable String readHtmlFile(String filename) {
        File file = new File(mContext.getFilesDir(), filename);

        return readHtmlFile(file);
    }

    public @Nullable String readHtmlFile(Table table) {
        return readHtmlFile(getFilename(Uri.parse(table.getUri()), table.getPublishedDate()));
    }

    public @Nullable File exists(Table table) {
        return exists(Uri.parse(table.getUri()), table.getPublishedDate());
    }

    public int countFiles() {
        return listFiles().length;
    }

    public long occupiedStorage() {
        long sum = 0;

        for (File file :
                listFiles()) {
            sum += file.length();
        }

        return sum;
    }

    public void deleteAllFiles() {
        for (File file :
                listFiles()) {
            boolean deleted = file.delete();
            Log.d("MANUALDELETE", "could delete file " + file.getName() + "? " + deleted);
        }
    }

    public void getFile(Table table, DownloadManager downloadManager, Handler fileAvailableHandler, Response.ErrorListener errorListener) {
        File alreadyDownloadedFile = exists(Uri.parse(table.getUri()), table.getPublishedDate());

        if (alreadyDownloadedFile != null) {
            fileAvailableHandler.sendEmptyMessage(0);
        } else {
            if (table.isHtml()) {
                downloadManager.downloadHtmlTable(table, this, fileAvailableHandler, errorListener);
            } else {
                downloadManager.downloadImageTable(table, this, fileAvailableHandler, errorListener);
            }
        }
    }
}
