package com.example.lab3;

import android.Manifest;
import android.content.*;
import android.content.pm.PackageManager;
import android.os.*;
import android.util.Log;
import android.widget.*;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import java.net.HttpURLConnection;
import java.net.URL;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private static final int REQUEST_WRITE_PERMISSION = 1;

    private EditText etAddress;
    private TextView tvFileSizeValue, tvFileTypeValue, tvDownloadProgressValue;
    private ProgressBar pbDownload;

    private FileInfo fileInfo = new FileInfo();
    private ProgressInfo progressInfo = new ProgressInfo();

    private final BroadcastReceiver progressReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            progressInfo = intent.getParcelableExtra(DownloadService.PROGRESS_KEY);
            updateProgress();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initUI();
        restoreState(savedInstanceState);
    }

    private void initUI() {
        etAddress = findViewById(R.id.etAddress);
        tvFileSizeValue = findViewById(R.id.tvFileSizeValue);
        tvFileTypeValue = findViewById(R.id.tvFileTypeValue);
        tvDownloadProgressValue = findViewById(R.id.tvDownloadProgressValue);
        pbDownload = findViewById(R.id.pbDownload);

        findViewById(R.id.btnDownloadInfo).setOnClickListener(v -> fetchFileInfo());
        findViewById(R.id.btnDownloadFile).setOnClickListener(v -> tryDownload());
    }

    private void fetchFileInfo() {
        String url = etAddress.getText().toString().trim();
        if (url.isEmpty()) {
            showToast(R.string.podaj_url);
        } else {
            new FileInfoTask().execute(url);
        }
    }

    private void tryDownload() {
        String url = etAddress.getText().toString().trim();
        if (url.isEmpty()) {
            showToast(R.string.podaj_url);
            return;
        }

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED) {
            startDownload(url);
        } else {
            requestStoragePermission();
        }
    }

    private void requestStoragePermission() {
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            showToast(R.string.dodaj_uprawnienia);
        }

        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_WRITE_PERMISSION);
    }

    private void startDownload(String url) {
        DownloadService.startDownload(this, url);
        showToast(R.string.pobieranie_niewiadomo);
    }

    private void showToast(int resId) {
        Toast.makeText(this, getText(resId), Toast.LENGTH_SHORT).show();
    }

    private void updateProgress() {
        if (progressInfo == null) return;

        if (progressInfo.fileSize > 0) {
            int percent = (int) (progressInfo.downloadedBytes * 100 / progressInfo.fileSize);
            pbDownload.setIndeterminate(false);
            pbDownload.setProgress(percent);
            tvDownloadProgressValue.setText(percent + "%");
        } else {
            pbDownload.setIndeterminate(true);
            tvDownloadProgressValue.setText(R.string.pobieranie_niewiadomo);
        }

        switch (progressInfo.status) {
            case ProgressInfo.STATUS_COMPLETED:
                tvDownloadProgressValue.setText(R.string.pobrano_plik);
                break;
            case ProgressInfo.STATUS_ERROR:
                tvDownloadProgressValue.setText(R.string.blad_pobierania);
                break;
        }
    }

    private void updateFileInfo() {
        tvFileSizeValue.setText(String.valueOf(Math.max(fileInfo.contentLength, 0)));
        tvFileTypeValue.setText(fileInfo.contentType != null ? fileInfo.contentType : "");
    }

    private void restoreState(Bundle state) {
        if (state == null) return;

        etAddress.setText(state.getString("url", ""));
        fileInfo.contentLength = state.getInt("contentLength", 0);
        fileInfo.contentType = state.getString("contentType", "");
        progressInfo = state.getParcelable("progressInfo");

        updateFileInfo();
        updateProgress();
    }

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        outState.putString("url", etAddress.getText().toString());
        outState.putInt("contentLength", fileInfo.contentLength);
        outState.putString("contentType", fileInfo.contentType);
        outState.putParcelable("progressInfo", progressInfo);
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onResume() {
        super.onResume();
        LocalBroadcastManager.getInstance(this).registerReceiver(
                progressReceiver, new IntentFilter(DownloadService.BROADCAST_PROGRESS));
    }

    @Override
    protected void onPause() {
        super.onPause();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(progressReceiver);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] results) {
        super.onRequestPermissionsResult(requestCode, permissions, results);
        if (requestCode == REQUEST_WRITE_PERMISSION &&
                results.length > 0 &&
                results[0] == PackageManager.PERMISSION_GRANTED) {
            startDownload(etAddress.getText().toString());
        } else {
            showToast(R.string.dodaj_uprawnienia);
        }
    }

    private static class FileInfo {
        int contentLength;
        String contentType;
    }

    private class FileInfoTask extends AsyncTask<String, Void, FileInfo> {
        @Override
        protected FileInfo doInBackground(String... urls) {
            FileInfo info = new FileInfo();
            try {
                HttpURLConnection conn = (HttpURLConnection) new URL(urls[0]).openConnection();
                conn.setRequestMethod("GET");
                conn.connect();
                info.contentLength = conn.getContentLength();
                info.contentType = conn.getContentType();
                conn.disconnect();
            } catch (Exception e) {
                Log.e(TAG, "Błąd pobierania informacji o pliku", e);
                info.contentLength = -1;
                info.contentType = "err";
            }
            return info;
        }

        @Override
        protected void onPostExecute(FileInfo result) {
            fileInfo = result;
            updateFileInfo();
        }
    }
}
