/*
 * 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.settings.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.net.NetworkStatsHistory;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.android.internal.util.Preconditions;
import com.android.settings.R;

import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;

/**
 * {@link NetworkStatsHistory} series to render inside a {@link ChartView},
 * using {@link ChartAxis} to map into screen coordinates.
 */
public class ChartNetworkSeriesView extends View {
    private static final String TAG = "ChartNetworkSeriesView";
    private static final boolean LOGD = false;

    private static final boolean ESTIMATE_ENABLED = false;

    private ChartAxis mHoriz;
    private ChartAxis mVert;

    private Paint mPaintStroke;
    private Paint mPaintFill;
    private Paint mPaintFillSecondary;
    private Paint mPaintEstimate;

    private NetworkStatsHistory mStats;

    private Path mPathStroke;
    private Path mPathFill;
    private Path mPathEstimate;

    private int mSafeRegion;

    private long mStart;
    private long mEnd;

    /** Series will be extended to reach this end time. */
    private long mEndTime = Long.MIN_VALUE;

    private boolean mPathValid = false;
    private boolean mEstimateVisible = false;
    private boolean mSecondary = false;

    private long mMax;
    private long mMaxEstimate;

    public ChartNetworkSeriesView(Context context) {
        this(context, null, 0);
    }

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

    public ChartNetworkSeriesView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        final TypedArray a = context.obtainStyledAttributes(
                attrs, R.styleable.ChartNetworkSeriesView, defStyle, 0);

        final int stroke = a.getColor(R.styleable.ChartNetworkSeriesView_strokeColor, Color.RED);
        final int fill = a.getColor(R.styleable.ChartNetworkSeriesView_fillColor, Color.RED);
        final int fillSecondary = a.getColor(
                R.styleable.ChartNetworkSeriesView_fillColorSecondary, Color.RED);
        final int safeRegion = a.getDimensionPixelSize(
                R.styleable.ChartNetworkSeriesView_safeRegion, 0);

        setChartColor(stroke, fill, fillSecondary);
        setSafeRegion(safeRegion);
        setWillNotDraw(false);

        a.recycle();

        mPathStroke = new Path();
        mPathFill = new Path();
        mPathEstimate = new Path();
    }

    void init(ChartAxis horiz, ChartAxis vert) {
        mHoriz = Preconditions.checkNotNull(horiz, "missing horiz");
        mVert = Preconditions.checkNotNull(vert, "missing vert");
    }

    public void setChartColor(int stroke, int fill, int fillSecondary) {
        mPaintStroke = new Paint();
        mPaintStroke.setStrokeWidth(4.0f * getResources().getDisplayMetrics().density);
        mPaintStroke.setColor(stroke);
        mPaintStroke.setStyle(Style.STROKE);
        mPaintStroke.setAntiAlias(true);

        mPaintFill = new Paint();
        mPaintFill.setColor(fill);
        mPaintFill.setStyle(Style.FILL);
        mPaintFill.setAntiAlias(true);

        mPaintFillSecondary = new Paint();
        mPaintFillSecondary.setColor(fillSecondary);
        mPaintFillSecondary.setStyle(Style.FILL);
        mPaintFillSecondary.setAntiAlias(true);

        mPaintEstimate = new Paint();
        mPaintEstimate.setStrokeWidth(3.0f);
        mPaintEstimate.setColor(fillSecondary);
        mPaintEstimate.setStyle(Style.STROKE);
        mPaintEstimate.setAntiAlias(true);
        mPaintEstimate.setPathEffect(new DashPathEffect(new float[] { 10, 10 }, 1));
    }

    public void setSafeRegion(int safeRegion) {
        mSafeRegion = safeRegion;
    }

    public void bindNetworkStats(NetworkStatsHistory stats) {
        mStats = stats;
        invalidatePath();
        invalidate();
    }

    public void setBounds(long start, long end) {
        mStart = start;
        mEnd = end;
    }

    public void setSecondary(boolean secondary) {
        mSecondary = secondary;
    }

    public void invalidatePath() {
        mPathValid = false;
        mMax = 0;
        invalidate();
    }

    /**
     * Erase any existing {@link Path} and generate series outline based on
     * currently bound {@link NetworkStatsHistory} data.
     */
    private void generatePath() {
        if (LOGD) Log.d(TAG, "generatePath()");

        mMax = 0;
        mPathStroke.reset();
        mPathFill.reset();
        mPathEstimate.reset();
        mPathValid = true;

        // bail when not enough stats to render
        if (mStats == null || mStats.size() < 2) {
            return;
        }

        final int width = getWidth();
        final int height = getHeight();

        boolean started = false;
        float lastX = 0;
        float lastY = height;
        long lastTime = mHoriz.convertToValue(lastX);

        // move into starting position
        mPathStroke.moveTo(lastX, lastY);
        mPathFill.moveTo(lastX, lastY);

        // TODO: count fractional data from first bucket crossing start;
        // currently it only accepts first full bucket.

        long totalData = 0;

        NetworkStatsHistory.Entry entry = null;

        final int start = mStats.getIndexBefore(mStart);
        final int end = mStats.getIndexAfter(mEnd);
        for (int i = start; i <= end; i++) {
            entry = mStats.getValues(i, entry);

            final long startTime = entry.bucketStart;
            final long endTime = startTime + entry.bucketDuration;

            final float startX = mHoriz.convertToPoint(startTime);
            final float endX = mHoriz.convertToPoint(endTime);

            // skip until we find first stats on screen
            if (endX < 0) continue;

            // increment by current bucket total
            totalData += entry.rxBytes + entry.txBytes;

            final float startY = lastY;
            final float endY = mVert.convertToPoint(totalData);

            if (lastTime != startTime) {
                // gap in buckets; line to start of current bucket
                mPathStroke.lineTo(startX, startY);
                mPathFill.lineTo(startX, startY);
            }

            // always draw to end of current bucket
            mPathStroke.lineTo(endX, endY);
            mPathFill.lineTo(endX, endY);

            lastX = endX;
            lastY = endY;
            lastTime = endTime;
        }

        // when data falls short, extend to requested end time
        if (lastTime < mEndTime) {
            lastX = mHoriz.convertToPoint(mEndTime);

            mPathStroke.lineTo(lastX, lastY);
            mPathFill.lineTo(lastX, lastY);
        }

        if (LOGD) {
            final RectF bounds = new RectF();
            mPathFill.computeBounds(bounds, true);
            Log.d(TAG, "onLayout() rendered with bounds=" + bounds.toString() + " and totalData="
                    + totalData);
        }

        // drop to bottom of graph from current location
        mPathFill.lineTo(lastX, height);
        mPathFill.lineTo(0, height);

        mMax = totalData;

        if (ESTIMATE_ENABLED) {
            // build estimated data
            mPathEstimate.moveTo(lastX, lastY);

            final long now = System.currentTimeMillis();
            final long bucketDuration = mStats.getBucketDuration();

            // long window is average over two weeks
            entry = mStats.getValues(lastTime - WEEK_IN_MILLIS * 2, lastTime, now, entry);
            final long longWindow = (entry.rxBytes + entry.txBytes) * bucketDuration
                    / entry.bucketDuration;

            long futureTime = 0;
            while (lastX < width) {
                futureTime += bucketDuration;

                // short window is day average last week
                final long lastWeekTime = lastTime - WEEK_IN_MILLIS + (futureTime % WEEK_IN_MILLIS);
                entry = mStats.getValues(lastWeekTime - DAY_IN_MILLIS, lastWeekTime, now, entry);
                final long shortWindow = (entry.rxBytes + entry.txBytes) * bucketDuration
                        / entry.bucketDuration;

                totalData += (longWindow * 7 + shortWindow * 3) / 10;

                lastX = mHoriz.convertToPoint(lastTime + futureTime);
                lastY = mVert.convertToPoint(totalData);

                mPathEstimate.lineTo(lastX, lastY);
            }

            mMaxEstimate = totalData;
        }

        invalidate();
    }

    public void setEndTime(long endTime) {
        mEndTime = endTime;
    }

    public void setEstimateVisible(boolean estimateVisible) {
        mEstimateVisible = ESTIMATE_ENABLED ? estimateVisible : false;
        invalidate();
    }

    public long getMaxEstimate() {
        return mMaxEstimate;
    }

    public long getMaxVisible() {
        final long maxVisible = mEstimateVisible ? mMaxEstimate : mMax;
        if (maxVisible <= 0 && mStats != null) {
            // haven't generated path yet; fall back to raw data
            final NetworkStatsHistory.Entry entry = mStats.getValues(mStart, mEnd, null);
            return entry.rxBytes + entry.txBytes;
        } else {
            return maxVisible;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int save;

        if (!mPathValid) {
            generatePath();
        }

        if (mEstimateVisible) {
            save = canvas.save();
            canvas.clipRect(0, 0, getWidth(), getHeight());
            canvas.drawPath(mPathEstimate, mPaintEstimate);
            canvas.restoreToCount(save);
        }

        final Paint paintFill = mSecondary ? mPaintFillSecondary : mPaintFill;

        save = canvas.save();
        canvas.clipRect(mSafeRegion, 0, getWidth(), getHeight() - mSafeRegion);
        canvas.drawPath(mPathFill, paintFill);
        canvas.restoreToCount(save);
    }
}
