/*
 * Copyright (C) 2013 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.applications;

import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.app.procstats.ProcessState;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.app.procstats.ServiceState;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public final class ProcStatsEntry implements Parcelable {

    private static final String TAG = "ProcStatsEntry";
    private static boolean DEBUG = ProcessStatsUi.DEBUG;

    final String mPackage;
    final int mUid;
    final String mName;
    public CharSequence mLabel;
    final ArrayList<String> mPackages = new ArrayList<>();
    final long mBgDuration;
    final long mAvgBgMem;
    final long mMaxBgMem;
    final double mBgWeight;
    final long mRunDuration;
    final long mAvgRunMem;
    final long mMaxRunMem;
    final double mRunWeight;

    String mBestTargetPackage;

    ArrayMap<String, ArrayList<Service>> mServices = new ArrayMap<>(1);

    public ProcStatsEntry(ProcessState proc, String packageName,
            ProcessStats.ProcessDataCollection tmpBgTotals,
            ProcessStats.ProcessDataCollection tmpRunTotals, boolean useUss) {
        proc.computeProcessData(tmpBgTotals, 0);
        proc.computeProcessData(tmpRunTotals, 0);
        mPackage = proc.getPackage();
        mUid = proc.getUid();
        mName = proc.getName();
        mPackages.add(packageName);
        mBgDuration = tmpBgTotals.totalTime;
        mAvgBgMem = useUss ? tmpBgTotals.avgUss : tmpBgTotals.avgPss;
        mMaxBgMem = useUss ? tmpBgTotals.maxUss : tmpBgTotals.maxPss;
        mBgWeight = mAvgBgMem * (double) mBgDuration;
        mRunDuration = tmpRunTotals.totalTime;
        mAvgRunMem = useUss ? tmpRunTotals.avgUss : tmpRunTotals.avgPss;
        mMaxRunMem = useUss ? tmpRunTotals.maxUss : tmpRunTotals.maxPss;
        mRunWeight = mAvgRunMem * (double) mRunDuration;
        if (DEBUG) Log.d(TAG, "New proc entry " + proc.getName() + ": dur=" + mBgDuration
                + " avgpss=" + mAvgBgMem + " weight=" + mBgWeight);
    }

    public ProcStatsEntry(String pkgName, int uid, String procName, long duration, long mem,
            long memDuration) {
        mPackage = pkgName;
        mUid = uid;
        mName = procName;
        mBgDuration = mRunDuration = duration;
        mAvgBgMem = mMaxBgMem = mAvgRunMem = mMaxRunMem = mem;
        mBgWeight = mRunWeight = ((double)memDuration) * mem;
        if (DEBUG) Log.d(TAG, "New proc entry " + procName + ": dur=" + mBgDuration
                + " avgpss=" + mAvgBgMem + " weight=" + mBgWeight);
    }

    public ProcStatsEntry(Parcel in) {
        mPackage = in.readString();
        mUid = in.readInt();
        mName = in.readString();
        in.readStringList(mPackages);
        mBgDuration = in.readLong();
        mAvgBgMem = in.readLong();
        mMaxBgMem = in.readLong();
        mBgWeight = in.readDouble();
        mRunDuration = in.readLong();
        mAvgRunMem = in.readLong();
        mMaxRunMem = in.readLong();
        mRunWeight = in.readDouble();
        mBestTargetPackage = in.readString();
        final int N = in.readInt();
        if (N > 0) {
            mServices.ensureCapacity(N);
            for (int i=0; i<N; i++) {
                String key = in.readString();
                ArrayList<Service> value = new ArrayList<Service>();
                in.readTypedList(value, Service.CREATOR);
                mServices.append(key, value);
            }
        }
    }

    public void addPackage(String packageName) {
        mPackages.add(packageName);
    }

    public void evaluateTargetPackage(PackageManager pm, ProcessStats stats,
            ProcessStats.ProcessDataCollection bgTotals,
            ProcessStats.ProcessDataCollection runTotals, Comparator<ProcStatsEntry> compare,
            boolean useUss) {
        mBestTargetPackage = null;
        if (mPackages.size() == 1) {
            if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": single pkg " + mPackages.get(0));
            mBestTargetPackage = mPackages.get(0);
            return;
        }

        // If one of the packages is the framework itself, that wins.
        // See if there is one significant package that was running here.
        for (int ipkg=0; ipkg<mPackages.size(); ipkg++) {
            if ("android".equals(mPackages.get(ipkg))) {
                mBestTargetPackage = mPackages.get(ipkg);
                return;
            }
        }

        // Collect information about each package running in the process.
        ArrayList<ProcStatsEntry> subProcs = new ArrayList<>();
        for (int ipkg=0; ipkg<mPackages.size(); ipkg++) {
            SparseArray<ProcessStats.PackageState> vpkgs
                    = stats.mPackages.get(mPackages.get(ipkg), mUid);
            for (int ivers=0;  ivers<vpkgs.size(); ivers++) {
                ProcessStats.PackageState pkgState = vpkgs.valueAt(ivers);
                if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ", pkg "
                        + pkgState + ":");
                if (pkgState == null) {
                    Log.w(TAG, "No package state found for " + mPackages.get(ipkg) + "/"
                            + mUid + " in process " + mName);
                    continue;
                }
                ProcessState pkgProc = pkgState.mProcesses.get(mName);
                if (pkgProc == null) {
                    Log.w(TAG, "No process " + mName + " found in package state "
                            + mPackages.get(ipkg) + "/" + mUid);
                    continue;
                }
                subProcs.add(new ProcStatsEntry(pkgProc, pkgState.mPackageName, bgTotals,
                        runTotals, useUss));
            }
        }

        if (subProcs.size() > 1) {
            Collections.sort(subProcs, compare);
            if (subProcs.get(0).mRunWeight > (subProcs.get(1).mRunWeight *3)) {
                if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": best pkg "
                        + subProcs.get(0).mPackage + " weight " + subProcs.get(0).mRunWeight
                        + " better than " + subProcs.get(1).mPackage
                        + " weight " + subProcs.get(1).mRunWeight);
                mBestTargetPackage = subProcs.get(0).mPackage;
                return;
            }
            // Couldn't find one that is best by weight, let's decide on best another
            // way: the one that has the longest running service, accounts for at least
            // half of the maximum weight, and has specified an explicit app icon.
            double maxWeight = subProcs.get(0).mRunWeight;
            long bestRunTime = -1;
            boolean bestPersistent = false;
            for (int i=0; i<subProcs.size(); i++) {
                final ProcStatsEntry subProc = subProcs.get(i);
                if (subProc.mRunWeight < (maxWeight/2)) {
                    if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
                            + subProc.mPackage + " weight " + subProc.mRunWeight
                            + " too small");
                    continue;
                }
                try {
                    ApplicationInfo ai = pm.getApplicationInfo(subProc.mPackage, 0);
                    if (ai.icon == 0) {
                        if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
                                + subProc.mPackage + " has no icon");
                        continue;
                    }
                    if ((ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0) {
                        long thisRunTime = subProc.mRunDuration;
                        if (!bestPersistent || thisRunTime > bestRunTime) {
                            if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
                                    + subProc.mPackage + " new best pers run time "
                                    + thisRunTime);
                            bestRunTime = thisRunTime;
                            bestPersistent = true;
                        } else {
                            if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
                                    + subProc.mPackage + " pers run time " + thisRunTime
                                    + " not as good as last " + bestRunTime);
                        }
                        continue;
                    } else if (bestPersistent) {
                        if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
                                + subProc.mPackage + " is not persistent");
                        continue;
                    }
                } catch (PackageManager.NameNotFoundException e) {
                    if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
                            + subProc.mPackage + " failed finding app info");
                    continue;
                }
                ArrayList<Service> subProcServices = null;
                for (int isp=0, NSP=mServices.size(); isp<NSP; isp++) {
                    ArrayList<Service> subServices = mServices.valueAt(isp);
                    if (subServices.get(0).mPackage.equals(subProc.mPackage)) {
                        subProcServices = subServices;
                        break;
                    }
                }
                long thisRunTime = 0;
                if (subProcServices != null) {
                    for (int iss=0, NSS=subProcServices.size(); iss<NSS; iss++) {
                        Service service = subProcServices.get(iss);
                        if (service.mDuration > thisRunTime) {
                            if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
                                    + subProc.mPackage + " service " + service.mName
                                    + " run time is " + service.mDuration);
                            thisRunTime = service.mDuration;
                            break;
                        }
                    }
                }
                if (thisRunTime > bestRunTime) {
                    if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
                            + subProc.mPackage + " new best run time " + thisRunTime);
                    mBestTargetPackage = subProc.mPackage;
                    bestRunTime = thisRunTime;
                } else {
                    if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
                            + subProc.mPackage + " run time " + thisRunTime
                            + " not as good as last " + bestRunTime);
                }
            }
            // Final fallback, just pick the first subProc.
            if (TextUtils.isEmpty(mBestTargetPackage)) {
                mBestTargetPackage = subProcs.get(0).mPackage;
            }
        } else if (subProcs.size() == 1) {
            mBestTargetPackage = subProcs.get(0).mPackage;
        }
    }

    public void addService(ServiceState svc) {
        ArrayList<Service> services = mServices.get(svc.getPackage());
        if (services == null) {
            services = new ArrayList<Service>();
            mServices.put(svc.getPackage(), services);
        }
        services.add(new Service(svc));
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mPackage);
        dest.writeInt(mUid);
        dest.writeString(mName);
        dest.writeStringList(mPackages);
        dest.writeLong(mBgDuration);
        dest.writeLong(mAvgBgMem);
        dest.writeLong(mMaxBgMem);
        dest.writeDouble(mBgWeight);
        dest.writeLong(mRunDuration);
        dest.writeLong(mAvgRunMem);
        dest.writeLong(mMaxRunMem);
        dest.writeDouble(mRunWeight);
        dest.writeString(mBestTargetPackage);
        final int N = mServices.size();
        dest.writeInt(N);
        for (int i=0; i<N; i++) {
            dest.writeString(mServices.keyAt(i));
            dest.writeTypedList(mServices.valueAt(i));
        }
    }

    public static final Parcelable.Creator<ProcStatsEntry> CREATOR
            = new Parcelable.Creator<ProcStatsEntry>() {
        public ProcStatsEntry createFromParcel(Parcel in) {
            return new ProcStatsEntry(in);
        }

        public ProcStatsEntry[] newArray(int size) {
            return new ProcStatsEntry[size];
        }
    };

    public static final class Service implements Parcelable {
        final String mPackage;
        final String mName;
        final String mProcess;
        final long mDuration;

        public Service(ServiceState service) {
            mPackage = service.getPackage();
            mName = service.getName();
            mProcess = service.getProcessName();
            mDuration = service.dumpTime(null, null,
                    ServiceState.SERVICE_RUN, ProcessStats.STATE_NOTHING, 0, 0);
        }

        public Service(Parcel in) {
            mPackage = in.readString();
            mName = in.readString();
            mProcess = in.readString();
            mDuration = in.readLong();
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(mPackage);
            dest.writeString(mName);
            dest.writeString(mProcess);
            dest.writeLong(mDuration);
        }

        public static final Parcelable.Creator<Service> CREATOR
                = new Parcelable.Creator<Service>() {
            public Service createFromParcel(Parcel in) {
                return new Service(in);
            }

            public Service[] newArray(int size) {
                return new Service[size];
            }
        };
    }
}
