package com.snap.wall.activity;

import android.app.WallpaperManager;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target;
import com.snap.wall.Wallpaper;
import com.snap.wall.adapter.OnSelecttype;
import com.snap.wall.databinding.ActivityPreviewBinding;
import com.snap.wall.bean.Information;
import com.snap.wall.fragment.Mydialog;
import com.snap.wall.mytool.Comutils;
import com.snap.wall.mytool.ObectManager;
import com.snap.wall.R;
import com.snap.wall.mytool.JsonData;

import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;

import okhttp3.Call;

public class PreviewActivity extends AppCompatActivity implements OnSelecttype {

    private Information data;
    private WallpaperManager wallpaperManager;
    private final int permissionCode = 1;
    private String mSavePath;
    private String imId;
    private String fullUrl;

    private Mydialog dialogType;
    private File downloadFile;
    private Call call;
    private ActivityPreviewBinding vb;

    private Timer clockTimer;
    private Handler mainHandler;
    private final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm", Locale.CHINA);
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd EEEE", Locale.ENGLISH);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        vb = ActivityPreviewBinding.inflate(getLayoutInflater());
        Comutils.initFull(this, true);
        setContentView(vb.getRoot());

        data = (Information) getIntent().getSerializableExtra(Comutils.key_info);
        if (data == null) {
            finish();
            return;
        }
        imId = data.getImId();
        mSavePath = JsonData.INSTANCE.getSaveFilePath(this, imId);
        fullUrl = data.getFullUrl();
        wallpaperManager = WallpaperManager.getInstance(this);

        mainHandler = new Handler(Looper.getMainLooper());

        addToRecentWallpapers();

        initClick();
        loadDetail();
        vb.tvContent.setText(data.getDescription());
        initClockWeather();
        startClockRefresh();
    }

    private void addToRecentWallpapers() {
        if (data == null) return;

        Wallpaper wallpaper = new Wallpaper();
        wallpaper.setId(data.getImId());
        wallpaper.setTitle(data.getDescription() != null ? data.getDescription() : "Wallpaper " + data.getImId());
        wallpaper.setImageUrl(data.getFullUrl() != null ? data.getFullUrl() : data.getPreviewUrl1080());
        wallpaper.setViewTime(System.currentTimeMillis());

    }

    private void initClockWeather() {
        updateClockWeather();
        vb.tvWeather.setText("晴 25℃");
    }

    private void startClockRefresh() {
        if (clockTimer != null) {
            clockTimer.cancel();
        }
        clockTimer = new Timer();
        clockTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (!isDestroyed() && mainHandler != null) {
                    mainHandler.post(PreviewActivity.this::updateClockWeather);
                }
            }
        }, 0, 1000);
    }

    private void updateClockWeather() {
        Date currentTime = new Date();
        vb.tvClock.setText(timeFormat.format(currentTime));
        vb.tvDate.setText(dateFormat.format(currentTime));

        int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
        if (hour >= 18 || hour < 6) {
            vb.tvWeather.setText("Night 18℃");
        } else if (hour >= 12 && hour < 18) {
            vb.tvWeather.setText("Sunny 28℃");
        } else {
            vb.tvWeather.setText("Sunny 25℃");
        }
    }

    private void loadDetail() {
        String previewUrl400 = data.getPreviewUrl400();
        String previewUrl1080 = data.getPreviewUrl1080();

        File file = new File(mSavePath);
        RequestOptions options = new RequestOptions().format(DecodeFormat.PREFER_RGB_565);

        if (file.exists()) {
            Glide.with(this)
                    .load(file)
                    .apply(options)
                    .placeholder(R.mipmap.im_placeholder)
                    .transition(DrawableTransitionOptions.withCrossFade(500))
                    .fitCenter()
                    .into(vb.imageviewPreview);
        } else {
            Glide.with(this)
                    .asDrawable()
                    .load(previewUrl1080)
                    .apply(options)
                    .skipMemoryCache(true)
                    .placeholder(R.mipmap.im_placeholder)
                    .thumbnail(Glide.with(this)
                            .asDrawable()
                            .load(previewUrl400)
                            .apply(options)
                            .placeholder(R.mipmap.im_placeholder)
                            .fitCenter())
                    .transition(DrawableTransitionOptions.withCrossFade(500))
                    .listener(new RequestListener<Drawable>() {
                        @Override
                        public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
                            return false;
                        }

                        @Override
                        public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
                            return false;
                        }
                    })
                    .fitCenter()
                    .into(vb.imageviewPreview);
        }

        vb.imageFavorite.setSelected(ObectManager.queryIsLike(imId));
    }

    private void initClick() {
        vb.imageviewBack.setOnClickListener(v -> finish());

        vb.buttonSet.setOnClickListener(v -> {
            if (dialogType == null) {
                dialogType = new Mydialog();
                dialogType.setListener(this);
            }
            if (!dialogType.isAdded()) {
                dialogType.show(getSupportFragmentManager(), "");
            }
        });

        vb.imageFavorite.setOnClickListener(v -> {
            boolean isSelected = vb.imageFavorite.isSelected();
            vb.imageFavorite.setSelected(!isSelected);
            data.setLike(!isSelected);
            ObectManager.updateLike(data);
        });

        vb.layoutDownload.setOnClickListener(v -> {
            if (JsonData.INSTANCE.requestPermission(this, permissionCode)) {
                startSaveToAlbum();
            }
        });
    }

    private void startSaveToAlbum() {
        showDownloadLoading(true);
        if (downloadFile != null && downloadFile.exists()) {
            startSave(downloadFile);
            return;
        }
        doDownload(true, true);
    }

    private void doDownload(boolean showMsg, boolean save) {
        call = JsonData.INSTANCE.downloadFile(fullUrl, mSavePath, (aBoolean, inputStream) -> {
            File file = new File(mSavePath);
            if (aBoolean && file.exists()) {
                downloadFile = file;
                if (save) {
                    startSave(downloadFile);
                }
            } else if (showMsg) {
                runOnUiThread(() -> {
                    showDownloadLoading(false);
                    Toast.makeText(PreviewActivity.this, getString(R.string.download_fail), Toast.LENGTH_SHORT).show();
                });
            }
            return null;
        });
    }

    private void showDownloadLoading(boolean show) {
        vb.pbDownload.setVisibility(show ? View.VISIBLE : View.GONE);
        vb.imageDownload.setVisibility(show ? View.GONE : View.VISIBLE);
    }

    private void showSetWallpaperLoading(boolean show) {
        vb.pbSet.setVisibility(show ? View.VISIBLE : View.GONE);
        vb.buttonSet.setVisibility(show ? View.GONE : View.VISIBLE);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == permissionCode && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            startSaveToAlbum();
        }
    }

    private void startSave(File file) {
        ObectManager.insertOrUpdateDownload(data);
        Uri uri = JsonData.INSTANCE.saveToGallery(this, file);
        runOnUiThread(() -> {
            showDownloadLoading(false);
            Toast.makeText(this, uri == null ? R.string.save_fail : R.string.save_success,
                    uri == null ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG).show();
        });
    }

    @Override
    public void onSelectType(int type) {
        showSetWallpaperLoading(true);
        if (downloadFile != null && downloadFile.exists()) {
            new Thread(() -> setWallpaper(downloadFile, type)).start();
        } else {
            call = JsonData.INSTANCE.downloadFile(fullUrl, mSavePath, (aBoolean, inputStream) -> {
                File file = new File(mSavePath);
                if (aBoolean && file.exists()) {
                    downloadFile = file;
                    setWallpaper(downloadFile, type);
                } else {
                    runOnUiThread(() -> {
                        showSetWallpaperLoading(false);
                        Toast.makeText(PreviewActivity.this, R.string.set_fail, Toast.LENGTH_SHORT).show();
                    });
                }
                return null;
            });
        }
    }

    private void setWallpaper(File file, int type) {
        try (FileInputStream fis = new FileInputStream(file)) {
            switch (type) {
                case Mydialog.type_home:
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        wallpaperManager.setStream(fis, null, true, WallpaperManager.FLAG_SYSTEM);
                    } else {
                        wallpaperManager.setStream(fis);
                    }
                    break;
                case Mydialog.type_lock:
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        wallpaperManager.setStream(fis, null, true, WallpaperManager.FLAG_LOCK);
                    } else {
                        wallpaperManager.setStream(fis);
                    }
                    break;
                case Mydialog.type_both:
                    wallpaperManager.setStream(fis);
                    break;
            }
            if (file.exists()) {
                file.delete();
            }
            runOnUiThread(() -> {
                showSetWallpaperLoading(false);
                Toast.makeText(this, R.string.set_success, Toast.LENGTH_SHORT).show();
            });
        } catch (Exception e) {
            runOnUiThread(() -> {
                showSetWallpaperLoading(false);
                Toast.makeText(this, R.string.set_fail, Toast.LENGTH_SHORT).show();
            });
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (clockTimer != null) {
            clockTimer.cancel();
            clockTimer = null;
        }
        if (mainHandler != null) {
            mainHandler.removeCallbacksAndMessages(null);
        }
        if (call != null) {
            call.cancel();
        }
        if (dialogType != null && dialogType.isAdded()) {
            dialogType.dismiss();
        }
    }
}