/*
 * Copyright (C) 2017 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.systemui.statusbar.car;

import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import com.android.systemui.R;

import java.lang.ref.WeakReference;

/**
 * Displays the dots underneath the ViewPager on the lock screen. This is really just a simplified
 * version of PagerTitleStrip. We don't inherit from there because it's impossible to bypass some
 * of the overriden logic in that class.
 */
public class PageIndicator extends View {
    private static final String TAG = "PageIndicator";
    // These can be made a styleable attribute in the future if necessary.
    private static final int SELECTED_COLOR = 0xFFF5F5F5;  // grey 100
    private static final int UNSELECTED_COLOR = 0xFFBDBDBD;  // grey 400
    private final PageListener mPageListener = new PageListener();

    private ViewPager mPager;
    private WeakReference<PagerAdapter> mWatchingAdapter;

    private int mPageCount;
    private int mCurrentPosition;
    private Paint mPaint;
    private int mRadius;
    private int mStep;

    public PageIndicator(Context context) {
        super(context);
        init();
    }

    public PageIndicator(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.FILL);
        mRadius = getResources().getDimensionPixelSize(R.dimen.car_page_indicator_dot_diameter) / 2;
        mStep = mRadius * 3;
    }

    public void setupWithViewPager(ViewPager pager) {
        mPager = pager;

        final PagerAdapter adapter = (PagerAdapter) pager.getAdapter();
        pager.addOnPageChangeListener(mPageListener);
        pager.addOnAdapterChangeListener(mPageListener);
        updateAdapter(mWatchingAdapter != null ? mWatchingAdapter.get() : null, adapter);
        invalidate();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mPager != null) {
            updateAdapter(mPager.getAdapter(), null);
            mPager.removeOnPageChangeListener(mPageListener);
            mPager.removeOnAdapterChangeListener(mPageListener);
            mPager = null;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int x = canvas.getWidth() / 2 - (mPageCount / 2) * mStep;
        int y = canvas.getHeight() / 2;

        for (int i = 0; i < mPageCount; i++) {
            if (i == mCurrentPosition) {
                mPaint.setColor(SELECTED_COLOR);
            } else {
                mPaint.setColor(UNSELECTED_COLOR);
            }

            canvas.drawCircle(x, y, mRadius, mPaint);
            x += mStep;
        }
    }

    void updateAdapter(PagerAdapter oldAdapter, PagerAdapter newAdapter) {
        if (oldAdapter != null) {
            oldAdapter.unregisterDataSetObserver(mPageListener);
            mWatchingAdapter = null;
        }

        if (newAdapter != null) {
            newAdapter.registerDataSetObserver(mPageListener);
            mWatchingAdapter = new WeakReference<>(newAdapter);
        }

        updateDots();

        if (mPager != null) {
            requestLayout();
        }
    }

    private <T> T getRef(WeakReference<T> weakRef) {
        if (weakRef == null) {
            return null;
        }
        return weakRef.get();
    }

    private void updateDots() {
        PagerAdapter adapter = getRef(mWatchingAdapter);
        if (adapter == null) {
            return;
        }

        int count = adapter.getCount();
        if (mPageCount == count) {
            // Nothing to be done.
            return;
        }

        mPageCount = count;
        mCurrentPosition = 0;
        invalidate();
    }

    private class PageListener extends DataSetObserver implements ViewPager.OnPageChangeListener,
            ViewPager.OnAdapterChangeListener {

        @Override
        public void onPageScrolled(int unused1, float unused2, int unused3) { }

        @Override
        public void onPageSelected(int position) {
            if (mCurrentPosition == position) {
                return;
            }

            if (mPageCount <= position) {
                Log.e(TAG, "Position out of bounds, position=" + position + " size=" + mPageCount);
                return;
            }

            mCurrentPosition = position;
            invalidate();
        }

        @Override
        public void onPageScrollStateChanged(int state) { }

        @Override
        public void onAdapterChanged(ViewPager viewPager, PagerAdapter oldAdapter,
                PagerAdapter newAdapter) {
            updateAdapter(oldAdapter, newAdapter);
        }

        @Override
        public void onChanged() {
            updateDots();
        }
    }
}
