package com.example.lab3;

import android.app.*;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import androidx.core.app.NotificationCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import java.io.*;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

public class DownloadService extends IntentService {
    private static final String TAG = "DownloadService";

    private static final String ACTION_DOWNLOAD = "com.example.lab3.action.download_file";
    private static final String URL_KEY = "url";

    public static final String BROADCAST_PROGRESS = "com.example.lab3.broadcast.download_progress";
    public static final String PROGRESS_KEY = "progressInfo";

    private static final int NOTIFICATION_ID = 1;
    private static final String CHANNEL_ID = "download_channel";
    private static final int BUFFER_SIZE = 4096;

    private NotificationManager notificationManager;
    private ProgressInfo progressInfo;

    public DownloadService() {
        super("DownloadService");
    }

    public static void startDownload(Context context, String url) {
        Intent intent = new Intent(context, DownloadService.class);
        intent.setAction(ACTION_DOWNLOAD);
        intent.putExtra(URL_KEY, url);
        context.startService(intent);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent == null) return;

        if (ACTION_DOWNLOAD.equals(intent.getAction())) {
            String url = intent.getStringExtra(URL_KEY);
            if (url != null) {
                initService();
                startForeground(NOTIFICATION_ID, buildNotification());
                downloadFile(url);
            }
        }
    }

    private void initService() {
        progressInfo = new ProgressInfo();
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        createNotificationChannel();
    }

    private void createNotificationChannel() {
        NotificationChannel channel = new NotificationChannel(
                CHANNEL_ID,
                getString(R.string.app_name),
                NotificationManager.IMPORTANCE_LOW
        );
        notificationManager.createNotificationChannel(channel);
    }

    private Notification buildNotification() {
        Intent intent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = TaskStackBuilder.create(this)
                .addNextIntentWithParentStack(intent)
                .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle(getString(R.string.app_name))
                .setSmallIcon(android.R.drawable.ic_menu_save)
                .setContentIntent(pendingIntent)
                .setOngoing(true)
                .setChannelId(CHANNEL_ID);

        if (progressInfo.fileSize > 0) {
            int progress = (int) (progressInfo.downloadedBytes * 100 / progressInfo.fileSize);
            builder.setProgress(100, progress, false)
                    .setContentText(progress + "%");
        } else {
            builder.setProgress(0, 0, true)
                    .setContentText(getString(R.string.powiadomienie_pobieranie));
        }

        return builder.build();
    }

    private void downloadFile(String urlString) {
        HttpsURLConnection connection = null;
        DataInputStream input = null;
        FileOutputStream output = null;

        try {
            URL url = new URL(urlString);
            File outputFile = new File(getExternalFilesDir(null), new File(url.getFile()).getName());

            if (outputFile.exists()) outputFile.delete();

            connection = (HttpsURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();

            progressInfo.fileSize = connection.getContentLength();

            input = new DataInputStream(connection.getInputStream());
            output = new FileOutputStream(outputFile);

            byte[] buffer = new byte[BUFFER_SIZE];
            int bytesRead;

            while ((bytesRead = input.read(buffer)) != -1) {
                output.write(buffer, 0, bytesRead);
                progressInfo.downloadedBytes += bytesRead;

                updateNotification();
                broadcastProgress();
                Log.d(TAG, "Pobrano " + progressInfo.downloadedBytes + " z " + progressInfo.fileSize);
            }

            progressInfo.status = ProgressInfo.STATUS_COMPLETED;
            Log.d(TAG, "Pobrano plik: " + outputFile.getPath());

        } catch (Exception e) {
            progressInfo.status = ProgressInfo.STATUS_ERROR;
            Log.e(TAG, "Błąd podczas pobierania pliku", e);
        } finally {
            broadcastProgress();
            closeQuietly(input);
            closeQuietly(output);
            if (connection != null) connection.disconnect();
        }
    }

    private void updateNotification() {
        notificationManager.notify(NOTIFICATION_ID, buildNotification());
    }

    private void broadcastProgress() {
        Intent intent = new Intent(BROADCAST_PROGRESS);
        intent.putExtra(PROGRESS_KEY, progressInfo);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }

    private void closeQuietly(Closeable stream) {
        try {
            if (stream != null) stream.close();
        } catch (IOException e) {
            Log.e(TAG, "Błąd zamykania strumienia", e);
        }
    }
}
