package com.excelliance.open.gif;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;
import android.widget.ImageView;

import com.excelliance.open.BwbxUI;
import com.excelliance.open.LProgressActivity;
import com.excelliance.open.NextChapter;
import com.excelliance.open.PProgressActivity;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class GifImageView extends ImageView implements Runnable {
    private static final String TAG = "GifImageView";
    private GifDecoder gifDecoder;
    private Bitmap tmpBitmap;
    private final Handler handler = new Handler(Looper.getMainLooper());
    private boolean animating;
    private boolean renderFrame;
    private boolean shouldClear;
    private Thread animationThread;
    private OnFrameAvailable frameCallback = null;
    private long framesDisplayDuration = -1L;
    private OnAnimationStop animationStopCallback = null;
    private OnAnimationStart animationStartCallback = null;

    private int screenWidth = 0;
    private int screenHeight = 0;
    private Context mContext;
    private Resources mainRes = null;
    private Resources apkRes = null;
    private static final String GIF_NAME = "lebian_background.gif";

    private final Runnable updateResults = new Runnable() {
        @Override
        public void run() {
            if (tmpBitmap != null && !tmpBitmap.isRecycled()) {
                setImageBitmap(tmpBitmap);
            }
        }
    };

    private final Runnable cleanupRunnable = new Runnable() {
        @Override
        public void run() {
            tmpBitmap = null;
            gifDecoder = null;
            animationThread = null;
            shouldClear = false;
        }
    };

    public GifImageView(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        mainRes = BwbxUI.getResources(context);
        apkRes = BwbxUI.getApkResources(context);
        mContext = context;
        //获取手机屏幕的匡高
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            DisplayMetrics displayMetrics = new DisplayMetrics();
            wm.getDefaultDisplay().getRealMetrics(displayMetrics);
            screenWidth = displayMetrics.widthPixels;
            screenHeight = displayMetrics.heightPixels;
        } else {
            screenWidth = wm.getDefaultDisplay().getWidth();
            screenHeight = wm.getDefaultDisplay().getHeight();
        }

        String className = NextChapter.class.getName();
        if (context instanceof LProgressActivity) {

            className   = LProgressActivity.class.getName();
        } else if (context instanceof PProgressActivity) {
            className   = PProgressActivity.class.getName();
        }
        Log.d(TAG, "SwitchView: className="+className);
        if (BwbxUI.isLandscape(context, className)) {
            if (screenHeight > screenWidth) {
                screenWidth = screenWidth + screenHeight;
                screenHeight = screenWidth - screenHeight;
                screenWidth = screenWidth - screenHeight;
            }
        }

        try {
            InputStream is = apkRes.getAssets().open(GIF_NAME);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int len = 0;
            byte[] buffer = new byte[8192];
            while ((len = is.read(buffer)) > 0) {
                baos.write(buffer, 0, len);
            }

            setBytes(baos.toByteArray());
            startAnimation();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public GifImageView(final Context context) {
        this(context,null);
    }

    public void setBytes(final byte[] bytes) {
        gifDecoder = new GifDecoder();
        try {
            gifDecoder.read(bytes);
        } catch (final Exception e) {
            gifDecoder = null;
            Log.e(TAG, e.getMessage(), e);
            return;
        }

        if (animating) {
            startAnimationThread();
        } else {
            gotoFrame(0);
        }
    }

    public void startAnimation() {
        animating = true;
        startAnimationThread();
    }

    public boolean isAnimating() {
        return animating;
    }

    public void stopAnimation() {
        animating = false;

        if (animationThread != null) {
            animationThread.interrupt();
            animationThread = null;
        }
    }

    public void gotoFrame(int frame) {
        if (gifDecoder.getCurrentFrameIndex() == frame) return;
        if (gifDecoder.setFrameIndex(frame - 1) && !animating) {
            renderFrame = true;
            startAnimationThread();
        }
    }

    public void resetAnimation() {
        gifDecoder.resetLoopIndex();
        gotoFrame(0);
    }

    public void clear() {
        animating = false;
        renderFrame = false;
        shouldClear = true;
        stopAnimation();
        handler.post(cleanupRunnable);
    }

    private boolean canStart() {
        return (animating || renderFrame) && gifDecoder != null && animationThread == null;
    }

    public int getGifWidth() {
        return gifDecoder.getWidth();
    }

    /**
     * Gets the number of frames read from file.
     *
     * @return frame count.
     */
    public int getFrameCount() {
        return gifDecoder.getFrameCount();
    }

    public int getGifHeight() {
        return gifDecoder.getHeight();
    }

    @Override
    public void run() {
        if (animationStartCallback != null) {
            animationStartCallback.onAnimationStart();
        }

        do {
            if (!animating && !renderFrame) {
                break;
            }
            boolean advance = gifDecoder.advance();

            //milliseconds spent on frame decode
            long frameDecodeTime = 0;
            try {
                long before = System.nanoTime();
                tmpBitmap = gifDecoder.getNextFrame();
                if (frameCallback != null) {
                    tmpBitmap = frameCallback.onFrameAvailable(tmpBitmap);
                }
                frameDecodeTime = (System.nanoTime() - before) / 1000000;
                handler.post(updateResults);
            } catch (final ArrayIndexOutOfBoundsException | IllegalArgumentException e) {
                Log.w(TAG, e);
            }

            renderFrame = false;
            if (!animating || !advance) {
                animating = false;
                break;
            }
            try {
                int delay = gifDecoder.getNextDelay();
                // Sleep for frame duration minus time already spent on frame decode
                // Actually we need next frame decode duration here,
                // but I use previous frame time to make code more readable
                delay -= frameDecodeTime;
                if (delay > 0) {
                    Thread.sleep(framesDisplayDuration > 0 ? framesDisplayDuration : delay);
                }
            } catch (final InterruptedException e) {
                // suppress exception
            }
        } while (animating);

        if (shouldClear) {
            handler.post(cleanupRunnable);
        }
        animationThread = null;

        if (animationStopCallback != null) {
            animationStopCallback.onAnimationStop();
        }
    }

    //将图片转化为适应屏幕的Bitmap类型
    public Bitmap picture(Bitmap bitmap){
        if(bitmap == null){
            return null;
        }
        int height = bitmap.getHeight();
        int width = bitmap.getWidth();
        float scaleWidth = ((float) screenWidth) / width;
        float scaleHeight = ((float) screenHeight) / height;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        float rad = Math.max(scaleWidth,scaleHeight);
        int xStart = 0;
        int yStart = 0;
        int sMode = BwbxUI.getGlobalInt(mContext, "SCALE_MODE_IN_NEXTCHAPTER", 0);
        if(sMode == 0){
            matrix.postScale(rad, rad);
            if(rad == scaleHeight){
                xStart = (int)((width-screenWidth/rad)/2);
                width = (int)(screenWidth/rad);
            }else{
                yStart = (int)((height-screenHeight/rad)/2);
                height = (int)(screenHeight/rad);
            }
        }else if(sMode == 1){
            matrix.postScale(rad, rad);
        }else {
            matrix.postScale(scaleWidth, scaleHeight);
        }
        Log.d(TAG,"scaleMode is " + sMode + ",rad is " + rad + ",xStart is " + xStart + ",yStart is "+ yStart);
        // 得到新的图片
        bitmap = Bitmap.createBitmap(bitmap, xStart, yStart, width, height, matrix, true);
        return bitmap;
    }

    public OnFrameAvailable getOnFrameAvailable() {
        return frameCallback;
    }

    public void setOnFrameAvailable(OnFrameAvailable frameProcessor) {
        this.frameCallback = frameProcessor;
    }

    public interface OnFrameAvailable {
        Bitmap onFrameAvailable(Bitmap bitmap);
    }

    public OnAnimationStop getOnAnimationStop() {
        return animationStopCallback;
    }

    public void setOnAnimationStop(OnAnimationStop animationStop) {
        this.animationStopCallback = animationStop;
    }

    public void setOnAnimationStart(OnAnimationStart animationStart) {
        this.animationStartCallback = animationStart;
    }

    public interface OnAnimationStop {
        void onAnimationStop();
    }

    public interface OnAnimationStart {
        void onAnimationStart();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        clear();
    }

    private void startAnimationThread() {
        if (canStart()) {
            animationThread = new Thread(this);
            animationThread.start();
        }
    }
}
