/*
 * Copyright (C) 2021 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 android.car.cts.powerpolicy;

import com.android.tradefed.log.LogUtil.CLog;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class CpmsFrameworkLayerStateInfo {
    private static final int STRING_BUILDER_BUF_SIZE = 1024;

    public static final String COMMAND = "dumpsys car_service --services"
            + " CarPowerManagementService";
    public static final String CURRENT_STATE_HDR = "mCurrentState:";
    public static final String CURRENT_POLICY_ID_HDR = "mCurrentPowerPolicyId:";
    public static final String PENDING_POLICY_ID_HDR = "mPendingPowerPolicyId:";
    public static final String CURRENT_POLICY_GROUP_ID_HDR = "mCurrentPowerPolicyGroupId:";
    public static final String NUMBER_POLICY_LISTENERS_HDR = "# of power policy change listener:";
    public static final String POWER_POLICY_GROUPS_HDR = "Power policy groups:";
    public static final String PREEMPTIVE_POWER_POLICY_HDR = "Preemptive power policy:";
    public static final String COMPONENT_STATE_HDR = "Power components state:";
    public static final String COMPONENT_CONTROLLED_HDR =
            "Components powered off by power policy:";
    public static final String COMPONENT_CHANGED_HDR = "Components changed by the last policy:";
    public static final String MONITORING_HW_HDR = "Monitoring HW state signal:";
    public static final String SILENT_MODE_BY_HW_HDR = "Silent mode by HW state signal:";
    public static final String FORCED_SILENT_MODE_HDR = "Forced silent mode:";

    private static final String[] COMPONENT_LIST = {"AUDIO", "MEDIA", "DISPLAY", "BLUETOOTH",
            "WIFI", "CELLULAR", "ETHERNET", "PROJECTION", "NFC", "INPUT", "VOICE_INTERACTION",
            "VISUAL_INTERACTION", "TRUSTED_DEVICE_DETECTION", "LOCATION", "MICROPHONE", "CPU"};
    private static final HashSet COMPONENT_SET = new HashSet(Arrays.asList(COMPONENT_LIST));

    private final ArrayList<String> mEnables;
    private final ArrayList<String> mDisables;
    private final ArrayList<String> mControlledEnables;
    private final ArrayList<String> mControlledDisables;
    private final String[] mChangedComponents;
    private final PowerPolicyGroups mPowerPolicyGroups;
    private final String mCurrentPolicyId;
    private final String mPendingPolicyId;
    private final String mCurrentPolicyGroupId;
    private final int mNumberPolicyListeners;
    private final boolean mMonitoringHw;
    private final boolean mSilentModeByHw;
    private final boolean mForcedSilentMode;
    private final int mCurrentState;

    private CpmsFrameworkLayerStateInfo(String currentPolicyId, String pendingPolicyId,
            String currentPolicyGroupId, int numberPolicyListeners, String[] changedComponents,
            ArrayList<String> enables, ArrayList<String> disables, PowerPolicyGroups policyGroups,
            ArrayList<String> controlledEnables, ArrayList<String> controlledDisables,
            boolean monitoringHw, boolean silentModeByHw, boolean forcedSilentMode,
            int currentState) {
        mEnables = enables;
        mDisables = disables;
        mControlledEnables = controlledEnables;
        mControlledDisables = controlledDisables;
        mChangedComponents = changedComponents;
        mPowerPolicyGroups = policyGroups;
        mCurrentPolicyId = currentPolicyId;
        mPendingPolicyId = pendingPolicyId;
        mCurrentPolicyGroupId = currentPolicyGroupId;
        mNumberPolicyListeners = numberPolicyListeners;
        mMonitoringHw = monitoringHw;
        mSilentModeByHw = silentModeByHw;
        mForcedSilentMode = forcedSilentMode;
        mCurrentState = currentState;
    }

    public String getCurrentPolicyId() {
        return mCurrentPolicyId;
    }

    public String getPendingPolicyId() {
        return mPendingPolicyId;
    }

    public int getCurrentState() {
        return mCurrentState;
    }

    public boolean getForcedSilentMode() {
        return mForcedSilentMode;
    }

    public PowerPolicyDef.PowerComponent[] getCurrentEnabledComponents() {
        return PowerPolicyDef.PowerComponent.asComponentArray(mEnables);
    }

    public PowerPolicyDef.PowerComponent[] getCurrentDisabledComponents() {
        return PowerPolicyDef.PowerComponent.asComponentArray(mDisables);
    }

    public String getCurrentPolicyGroupId() {
        return mCurrentPolicyGroupId;
    }

    public PowerPolicyGroups getPowerPolicyGroups() {
        return mPowerPolicyGroups;
    }

    public int getNumberPolicyListeners() {
        return mNumberPolicyListeners;
    }

    public boolean isComponentOn(String component) {
        return mEnables.contains(component);
    }

    public boolean isComponentOff(String component) {
        return mDisables.contains(component);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(STRING_BUILDER_BUF_SIZE);
        sb.append("mCurrentState=").append(mCurrentState).append(' ');
        sb.append("mCurrentPolicyId=").append(mCurrentPolicyId).append(' ');
        sb.append("mPendingPolicyId=").append(mPendingPolicyId).append(' ');
        sb.append("mCurrentPolicyGroupId=").append(mCurrentPolicyGroupId).append(' ');
        sb.append("mNumberPolicyListeners=").append(mNumberPolicyListeners).append(' ');
        sb.append("silentmode=").append(mMonitoringHw).append(',');
        sb.append(mSilentModeByHw).append(',').append(mForcedSilentMode).append(' ');
        sb.append("enables=").append(String.join(",", mEnables)).append(' ');
        sb.append("disables=").append(String.join(",", mDisables));
        sb.append("controlledEnables=").append(String.join(",", mControlledEnables)).append(' ');
        sb.append("controlledDisables=").append(String.join(",", mControlledDisables));
        sb.append("changedComponents=").append(String.join(",", mChangedComponents));
        return sb.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CpmsFrameworkLayerStateInfo that = (CpmsFrameworkLayerStateInfo) o;
        return mCurrentState == that.mCurrentState
                && mMonitoringHw == that.mMonitoringHw
                && mSilentModeByHw == that.mSilentModeByHw
                && mForcedSilentMode == that.mForcedSilentMode
                && mNumberPolicyListeners == that.mNumberPolicyListeners
                && mEnables.equals(that.mEnables)
                && mDisables.equals(that.mDisables)
                && mPowerPolicyGroups.equals(that.mPowerPolicyGroups)
                && mControlledEnables.equals(that.mControlledEnables)
                && mControlledDisables.equals(that.mControlledDisables)
                && Arrays.equals(mChangedComponents, that.mChangedComponents)
                && Objects.equals(mCurrentPolicyId, that.mCurrentPolicyId)
                && Objects.equals(mPendingPolicyId, that.mPendingPolicyId)
                && Objects.equals(mCurrentPolicyGroupId, that.mCurrentPolicyGroupId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mEnables, mDisables, mControlledEnables, mControlledDisables,
                mChangedComponents, mPowerPolicyGroups, mCurrentPolicyId, mPendingPolicyId,
                mCurrentPolicyGroupId, mCurrentState, mMonitoringHw, mSilentModeByHw,
                mForcedSilentMode, mNumberPolicyListeners);
    }

    public static CpmsFrameworkLayerStateInfo parse(String cmdOutput) throws Exception {
        int currentState = -1;
        String currentPolicyId = null;
        String pendingPolicyId = null;
        String currentPolicyGroupId = null;
        ArrayList<String> enables = null;
        ArrayList<String> disables = null;
        ArrayList<String> controlledEnables = null;
        ArrayList<String> controlledDisables = null;
        String[] changedComponents = null;
        PowerPolicyGroups policyGroups = null;
        boolean monitoringHw = false;
        boolean silentModeByHw = false;
        boolean forcedSilentMode = false;
        int numberPolicyListeners = 0;

        String[] lines = cmdOutput.split("\n");
        StateInfoParser parser = new StateInfoParser(lines);
        HashSet<String> headerCounter = new HashSet<String>();
        String header;
        while ((header = parser.searchHeader()) != null) {
            switch (header) {
                case CURRENT_STATE_HDR:
                    currentState = parser.getIntData(CURRENT_STATE_HDR);
                    break;
                case CURRENT_POLICY_ID_HDR:
                    currentPolicyId = parser.getStringData(CURRENT_POLICY_ID_HDR);
                    break;
                case PENDING_POLICY_ID_HDR:
                    pendingPolicyId = parser.getStringData(PENDING_POLICY_ID_HDR);
                    break;
                case CURRENT_POLICY_GROUP_ID_HDR:
                    currentPolicyGroupId = parser.getStringData(CURRENT_POLICY_GROUP_ID_HDR);
                    break;
                case POWER_POLICY_GROUPS_HDR:
                    ArrayList<String> groupList = parser.getStringArray(POWER_POLICY_GROUPS_HDR,
                            PREEMPTIVE_POWER_POLICY_HDR);
                    policyGroups = PowerPolicyGroups.parse(groupList);
                    break;
                case COMPONENT_STATE_HDR:
                    parser.parseComponentStates(COMPONENT_STATE_HDR,
                            COMPONENT_CONTROLLED_HDR, true);
                    enables = parser.getEnables();
                    disables = parser.getDisables();
                    Collections.sort(enables);
                    Collections.sort(disables);
                    break;
                case COMPONENT_CONTROLLED_HDR:
                    parser.parseComponentStates(COMPONENT_CONTROLLED_HDR,
                            COMPONENT_CHANGED_HDR, false);
                    controlledEnables = parser.getEnables();
                    controlledDisables = parser.getDisables();
                    Collections.sort(controlledEnables);
                    Collections.sort(controlledDisables);
                    break;
                case COMPONENT_CHANGED_HDR:
                    changedComponents = parser.getChangedComponents(COMPONENT_CHANGED_HDR,
                            MONITORING_HW_HDR);
                    break;
                case MONITORING_HW_HDR:
                    monitoringHw = parser.getBooleanData(MONITORING_HW_HDR);
                    break;
                case SILENT_MODE_BY_HW_HDR:
                    silentModeByHw = parser.getBooleanData(SILENT_MODE_BY_HW_HDR);
                    break;
                case FORCED_SILENT_MODE_HDR:
                    forcedSilentMode = parser.getBooleanData(FORCED_SILENT_MODE_HDR);
                    break;
                case NUMBER_POLICY_LISTENERS_HDR:
                    numberPolicyListeners = parser.getIntData(NUMBER_POLICY_LISTENERS_HDR);
                    break;
                default:
                    throw new IllegalArgumentException("parser header mismatch: " + header);
            }
            headerCounter.add(header);
        }

        if (headerCounter.size() != StateInfoParser.HEADERS.length) {
            String errMsg = "miss headers. got: " + headerCounter + " expected: "
                    + String.join(",", StateInfoParser.HEADERS);
            throw new IllegalArgumentException(errMsg);
        }

        return new CpmsFrameworkLayerStateInfo(currentPolicyId, pendingPolicyId,
                currentPolicyGroupId, numberPolicyListeners, changedComponents, enables,
                disables, policyGroups, controlledEnables, controlledDisables, monitoringHw,
                silentModeByHw, forcedSilentMode, currentState);
    }

    private static final class StateInfoParser {
        private static final String[] HEADERS = {
            CURRENT_STATE_HDR,
            CURRENT_POLICY_ID_HDR,
            PENDING_POLICY_ID_HDR,
            CURRENT_POLICY_GROUP_ID_HDR,
            NUMBER_POLICY_LISTENERS_HDR,
            COMPONENT_STATE_HDR,
            COMPONENT_CONTROLLED_HDR,
            POWER_POLICY_GROUPS_HDR,
            COMPONENT_CHANGED_HDR,
            MONITORING_HW_HDR,
            SILENT_MODE_BY_HW_HDR,
            FORCED_SILENT_MODE_HDR
        };
        private final String[] mLines;
        private ArrayList<String> mEnables;
        private ArrayList<String> mDisables;
        private int mIdx = 0;

        private StateInfoParser(String[] lines) {
            mLines = lines;
        }

        private ArrayList<String> getEnables() {
            return mEnables;
        }

        private ArrayList<String> getDisables() {
            return mDisables;
        }

        private int getIntData(String header) throws Exception {
            int val = 0;
            switch (header) {
                case CURRENT_STATE_HDR:
                    Pattern pattern = Pattern.compile("mCurrentState: CpmsState "
                            + "[^\\n]*carPowerStateListenerState=(\\d+)");
                    Matcher matcher = pattern.matcher(mLines[mIdx]);
                    if (!matcher.find()) {
                        throw new IllegalArgumentException("malformatted mCurrentState: "
                                + mLines[mIdx]);
                    }
                    val = Integer.parseInt(matcher.group(1));
                    break;
                case NUMBER_POLICY_LISTENERS_HDR:
                    int strLen = mLines[mIdx].length();
                    val = Integer.parseInt(mLines[mIdx].substring(strLen - 1).trim());
                    break;
                default:
                    break;
            }
            return val;
        }

        private String getStringData(String header) {
            String val = null;
            if (mLines[mIdx].trim().length() != header.length()) {
                val = mLines[mIdx].trim().substring(header.length()).trim();
            }
            return val;
        }

        private ArrayList<String> getStringArray(String startHdr, String endHdr)
                throws Exception {
            if (!mLines[mIdx].contains(startHdr)) {
                String errMsg = String.format("expected start header %s at line %d : %s",
                        startHdr, mIdx, mLines[mIdx]);
                throw new IllegalArgumentException(errMsg);
            }

            ArrayList<String> strArray = new ArrayList<String>();
            while (++mIdx < mLines.length && !mLines[mIdx].contains(endHdr)) {
                strArray.add(mLines[mIdx]);
            }
            mIdx--;

            if (mIdx == (mLines.length - 1)) {
                throw new IllegalArgumentException("reaches the end while get " + startHdr);
            }
            return strArray;
        }

        private void parseComponentStates(String startHdr, String endHdr,
                boolean hasStateInfo) throws Exception {
            mEnables = new ArrayList<String>();
            mDisables = new ArrayList<String>();
            while (mIdx < (mLines.length - 1) && !mLines[++mIdx].contains(endHdr)) {
                String stateStr = mLines[mIdx].trim();
                String[] vals = stateStr.split(":\\s");
                if (hasStateInfo && vals.length != 2) {
                    String errMsg = String.format("wrong format at %d in: %s ", mIdx, stateStr);
                    CLog.e(errMsg);
                    throw new IllegalArgumentException(errMsg);
                }

                for (int i = 0; i < vals.length; i++) {
                    vals[i] = vals[i].trim();
                }

                if (!COMPONENT_SET.contains(vals[0])) {
                    String errMsg = String.format("invalid component at %d with %s in: %s",
                            mIdx, vals[0], stateStr);
                    CLog.e(errMsg);
                    throw new IllegalArgumentException(errMsg);
                }

                if (hasStateInfo) {
                    if (vals[1].startsWith("on")) {
                        mEnables.add(vals[0]);
                    } else if (vals[1].startsWith("off")) {
                        mDisables.add(vals[0]);
                    } else {
                        String errMsg =
                                String.format("wrong state value at %d with (%s, %s) in: %s",
                                mIdx, vals[0], vals[1], stateStr);
                        CLog.e(errMsg);
                        throw new IllegalArgumentException(errMsg);
                    }
                } else {
                    mDisables.add(vals[0]);
                }
            }
            mIdx--;

            if (mIdx == (mLines.length - 1)) {
                throw new IllegalArgumentException("reaches the end while parse " + startHdr);
            }
        }

        private String[] getChangedComponents(String startHdr, String endHdr) {
            int idx = mLines[mIdx].indexOf(endHdr);
            String compStr;
            if (idx < 0) {
                compStr = mLines[mIdx].substring(startHdr.length());
            } else {
                compStr = mLines[mIdx].substring(startHdr.length(), idx);
                mLines[mIdx] = mLines[mIdx].substring(idx);
                mIdx--;
            }
            return compStr.split(",\\s*");
        }

        private boolean getBooleanData(String header) {
            return Boolean.parseBoolean(mLines[mIdx].trim().substring(header.length()).trim());
        }

        private String searchHeader() {
            String header = null;
            for (mIdx++; mIdx < mLines.length; mIdx++) {
                if (mLines[mIdx].trim().isEmpty()) {
                    continue;
                }

                int firstHdrPos = mLines[mIdx].length() + 1;
                for (int i = 0; i < HEADERS.length; i++) {
                    int tempHdrPos = mLines[mIdx].indexOf(HEADERS[i]);
                    if (tempHdrPos >= 0 && (firstHdrPos > tempHdrPos)) {
                        firstHdrPos = tempHdrPos;
                        header = HEADERS[i];
                    }
                }
                if (header != null) {
                    break;
                }
            }

            return header;
        }
    }
}
