/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.camera.ui;

import com.android.camera.R;

import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;

/**
 * A view that contains camera zoom control which could adjust the zoom in/out
 * if the camera supports zooming.
 */
public abstract class ZoomControl extends RelativeLayout implements Rotatable {
    // The states of zoom button.
    public static final int ZOOM_IN = 0;
    public static final int ZOOM_OUT = 1;
    public static final int ZOOM_STOP = 2;

    private static final String TAG = "ZoomControl";
    private static final int ZOOMING_INTERVAL = 1000; // milliseconds

    protected ImageView mZoomIn;
    protected ImageView mZoomOut;
    protected ImageView mZoomSlider;
    protected int mOrientation;
    private Handler mHandler;

    public interface OnZoomChangedListener {
        void onZoomValueChanged(int index);  // only for immediate zoom
        void onZoomStateChanged(int state);  // only for smooth zoom
    }

    // The interface OnZoomIndexChangedListener is used to inform the
    // ZoomIndexBar about the zoom index change. The index position is between
    // 0 (the index is zero) and 1.0 (the index is mZoomMax).
    public interface OnZoomIndexChangedListener {
        void onZoomIndexChanged(double indexPosition);
    }

    protected int mZoomMax, mZoomIndex;
    private boolean mSmoothZoomSupported;
    private OnZoomChangedListener mListener;
    private OnZoomIndexChangedListener mIndexListener;

    protected OnIndicatorEventListener mOnIndicatorEventListener;
    private int mState;
    private int mStep;

    protected final Runnable mRunnable = new Runnable() {
        public void run() {
            performZoom(mState, false);
        }
    };

    public ZoomControl(Context context, AttributeSet attrs) {
        super(context, attrs);
        mZoomIn = addImageView(context, R.drawable.ic_zoom_in);
        mZoomSlider = addImageView(context, R.drawable.ic_zoom_slider);
        mZoomOut = addImageView(context, R.drawable.ic_zoom_out);
        mHandler = new Handler();
    }

    public void startZoomControl() {
        mZoomSlider.setPressed(true);
        setZoomIndex(mZoomIndex); // Update the zoom index bar.
    }

    protected ImageView addImageView(Context context, int iconResourceId) {
        ImageView image = new RotateImageView(context);
        image.setImageResource(iconResourceId);
        if (iconResourceId == R.drawable.ic_zoom_slider) {
            image.setContentDescription(getResources().getString(
                    R.string.accessibility_zoom_control));
        } else {
            image.setContentDescription(getResources().getString(
                    R.string.empty));
        }
        addView(image);
        return image;
    }

    public void closeZoomControl() {
        mZoomSlider.setPressed(false);
        stopZooming();
        if (!mSmoothZoomSupported) mHandler.removeCallbacks(mRunnable);
        if (mOnIndicatorEventListener != null) {
            mOnIndicatorEventListener.onIndicatorEvent(
                    OnIndicatorEventListener.EVENT_LEAVE_ZOOM_CONTROL);
        }
    }

    public void setZoomMax(int zoomMax) {
        mZoomMax = zoomMax;

        // Layout should be requested as the maximum zoom level is the key to
        // show the correct zoom slider position.
        requestLayout();
    }

    public void setOnZoomChangeListener(OnZoomChangedListener listener) {
        mListener = listener;
    }

    public void setOnIndicatorEventListener(OnIndicatorEventListener listener) {
        mOnIndicatorEventListener = listener;
    }

    public void setZoomIndex(int index) {
        if (index < 0 || index > mZoomMax) {
            throw new IllegalArgumentException("Invalid zoom value:" + index);
        }
        mZoomIndex = index;
        invalidate();
    }

    public void setSmoothZoomSupported(boolean smoothZoomSupported) {
        mSmoothZoomSupported = smoothZoomSupported;
    }

    private boolean zoomIn() {
        return (mZoomIndex == mZoomMax) ? false : changeZoomIndex(mZoomIndex + mStep);
    }

    private boolean zoomOut() {
        return (mZoomIndex == 0) ? false : changeZoomIndex(mZoomIndex - mStep);
    }

    protected void setZoomStep(int step) {
        mStep = step;
    }

    private void stopZooming() {
        if (mSmoothZoomSupported) {
            if (mListener != null) mListener.onZoomStateChanged(ZOOM_STOP);
        }
    }

    // Called from ZoomControlWheel to change the zoom level.
    // TODO: merge the zoom control for both platforms.
    protected void performZoom(int state) {
        performZoom(state, true);
    }

    private void performZoom(int state, boolean fromUser) {
        if ((mState == state) && fromUser) return;
        if (fromUser) mHandler.removeCallbacks(mRunnable);
        mState = state;
        switch (state) {
            case ZOOM_IN:
                zoomIn();
                break;
            case ZOOM_OUT:
                zoomOut();
                break;
            case ZOOM_STOP:
                stopZooming();
                break;
        }
        if (!mSmoothZoomSupported) {
            // Repeat the zoom action on tablet as the user is still holding
            // the zoom slider.
            mHandler.postDelayed(mRunnable, ZOOMING_INTERVAL / mZoomMax);
        }
    }

    // Called from ZoomControlBar to change the zoom level.
    protected void performZoom(double zoomPercentage) {
        int index = (int) (mZoomMax * zoomPercentage);
        if (mZoomIndex == index) return;
        changeZoomIndex(index);
   }

    private boolean changeZoomIndex(int index) {
        if (mListener != null) {
            if (mSmoothZoomSupported) {
                int zoomType = (index < mZoomIndex) ? ZOOM_OUT : ZOOM_IN;
                if (((zoomType == ZOOM_IN) && (mZoomIndex != mZoomMax)) ||
                        ((zoomType == ZOOM_OUT) && (mZoomIndex != 0))) {
                    mListener.onZoomStateChanged(zoomType);
                }
            } else {
                if (index > mZoomMax) index = mZoomMax;
                if (index < 0) index = 0;
                mListener.onZoomValueChanged(index);
                mZoomIndex = index;
            }
        }
        return true;
    }

    public void setOrientation(int orientation) {
        mOrientation = orientation;
        int count = getChildCount();
        for (int i = 0 ; i < count ; ++i) {
            View view = getChildAt(i);
            if (view instanceof RotateImageView) {
                ((RotateImageView) view).setOrientation(orientation);
            }
        }
    }

    @Override
    public void setActivated(boolean activated) {
        super.setActivated(activated);
        mZoomIn.setActivated(activated);
        mZoomOut.setActivated(activated);
    }
}
