package com.gjiazhe.panoramaimageview;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.widget.ImageView;

/**
 * Created by gjz on 19/12/2016.
 */

public class PanoramaImageView extends ImageView {

    // Enable panorama effect or not
    private boolean mEnablePanoramaMode = true;

    // If true, the image scroll left when the device clockwise rotate along y-axis.
    private boolean mInvertScrollDirection = true;

    // Image's width and height
    private int mDrawableWidth;
    private int mDrawableHeight;

    // View's width and height
    private int mWidth;
    private int mHeight;

    // Image's offset along x-axis from initial state(center in the view).
    private float mMaxOffsetX;

    // The scroll progress, form -1 to 1.
    private float mProgress;

    // Show scroll bar or not
    private boolean mEnableScrollbar = true;

    // The paint to draw scrollbar
    private Paint mScrollbarPaint;

    public PanoramaImageView(Context context) {
        this(context, null);
    }

    public PanoramaImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PanoramaImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        super.setScaleType(ScaleType.CENTER_CROP);

        if (mEnableScrollbar) {
            initScrollbarPaint();
        }
    }

    public void initScrollbarPaint() {
        mScrollbarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mScrollbarPaint.setColor(Color.WHITE);
        mScrollbarPaint.setStrokeWidth(dp2px(1));
    }

    public void setGyroscopeObserver(GyroscopeObserver observer) {
        if (observer != null) {
            observer.addPanoramaImageView(this);
        }
    }

    void updateProgress(float progress) {
        if (mEnablePanoramaMode) {
            mProgress = progress;
            invalidate();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mWidth = getWidth() - getPaddingLeft() - getPaddingRight();
        mHeight = getHeight() - getPaddingTop() - getPaddingBottom();

        if (getDrawable() != null) {
            mDrawableWidth = getDrawable().getIntrinsicWidth();
            mDrawableHeight = getDrawable().getIntrinsicHeight();

            float imgScale = (float) mHeight / (float) mDrawableHeight;
            mMaxOffsetX = Math.abs((mDrawableWidth * imgScale - mWidth) * 0.5f);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (!mEnablePanoramaMode || getDrawable() == null || isInEditMode()) {
            super.onDraw(canvas);
            return;
        }

        // Draw image
        if (mDrawableWidth * mHeight > mDrawableHeight * mWidth) {
            float currentOffsetX = mMaxOffsetX * mProgress;
            if (mInvertScrollDirection) {
                currentOffsetX = -currentOffsetX;
            }
            canvas.save();
            canvas.translate(currentOffsetX, 0);
            super.onDraw(canvas);
            canvas.restore();
        }

        // Draw scrollbar
        if (mEnableScrollbar) {
            float barBgWidth = mWidth * 0.9f;
            float barWidth = barBgWidth * mWidth / mDrawableWidth;

            float barBgStartX = mWidth/2 - barBgWidth/2;
            float barBgEndX = barBgStartX + barBgWidth;
            float barStartX = mInvertScrollDirection ?
                    barBgStartX + (barBgWidth-barWidth)/2 * (1 + mProgress):
                    barBgStartX + (barBgWidth-barWidth)/2 * (1 - mProgress);
            float barEndX = barStartX + barWidth;
            float barY = mHeight * 0.9f;

            mScrollbarPaint.setAlpha(100);
            canvas.drawLine(barBgStartX, barY, barBgEndX, barY, mScrollbarPaint);
            mScrollbarPaint.setAlpha(255);
            canvas.drawLine(barStartX, barY, barEndX, barY, mScrollbarPaint);
        }
    }

    private float dp2px(int dp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().getDisplayMetrics());
    }

    public void setEnablePanoramaMode(boolean enable) {
        mEnablePanoramaMode = enable;
    }

    public boolean isPanoramaModeEnabled() {
        return mEnablePanoramaMode;
    }

    public void setInvertScrollDirection(boolean invert) {
        if (mInvertScrollDirection != invert) {
            mInvertScrollDirection = invert;
        }
    }

    public boolean isInvertScrollDirection() {
        return mInvertScrollDirection;
    }

    public void setEnableScrollbar(boolean enable) {
        if (mEnableScrollbar != enable){
            mEnableScrollbar = enable;
            if (mEnableScrollbar) {
                initScrollbarPaint();
            } else {
                mScrollbarPaint = null;
            }
        }
    }

    public boolean isScrollbarEnabled() {
        return mEnableScrollbar;
    }

    @Override
    public void setScaleType(ScaleType scaleType) {
        /**
         * Do nothing because PanoramaImageView only
         * supports {@link scaleType.CENTER_CROP}
         */
    }
}

@@ -267,34 +267,8 @@
 ue;%0A
-import android.view.View;%0A
 impo
@@ -930,22 +930,8 @@
 ress
-, form -1 to 1
 .%0A  
@@ -1101,24 +1101,117 @@
 lbarPaint;%0A%0A
+    // Observe scroll state%0A    private OnPanoramaScrollListener mOnPanoramaScrollListener;%0A%0A
     public P
@@ -2130,43 +2130,218 @@
 s = 
-progress;%0A            invalidate();
+mInvertScrollDirection? -progress : progress;%0A            invalidate();%0A            if (mOnPanoramaScrollListener != null) %7B%0A                mOnPanoramaScrollListener.onScrolled(this, -mProgress);%0A            %7D
 %0A   
@@ -3338,114 +3338,8 @@
 ss;%0A
-            if (mInvertScrollDirection) %7B%0A                currentOffsetX = -currentOffsetX;%0A            %7D%0A
     
@@ -3803,130 +3803,8 @@
 tX =
- mInvertScrollDirection ?%0A                    barBgStartX + (barBgWidth-barWidth)/2 * (1 + mProgress):%0A                   
  bar
@@ -5401,11 +5401,766 @@
 */%0A    %7D
+%0A%0A    /**%0A     * Interface definition for a callback to be invoked when the image is scrolling%0A     */%0A    public interface OnPanoramaScrollListener %7B%0A        /**%0A         * Call when the image is scrolling%0A         *%0A         * @param view the panoramaImageView shows the image%0A         *%0A         * @param offsetProgress value between (-1, 1) indicating the offset progress.%0A         *                 -1 means the image scrolls to show its left bound,%0A         *                 1 means the image scrolls to show its right bound.%0A         */%0A        void onScrolled(PanoramaImageView view, float offsetProgress);%0A    %7D%0A%0A    public void setOnPanoramaScrollListener(OnPanoramaScrollListener listener) %7B%0A        mOnPanoramaScrollListener = listener;%0A    %7D
 %0A%7D%0A

add listener