/*
 * 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.cts.tradefed.result;

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

import org.kxml2.io.KXmlSerializer;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.tests.getinfo.DeviceInfoConstants;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Data structure for the device info collected by CTS.
 * <p/>
 * Provides methods to serialize and deserialize from XML, as well as checks for consistency
 * when multiple devices are used to generate the report.
 */
class DeviceInfoResult extends AbstractXmlPullParser {
    static final String TAG = "DeviceInfo";
    private static final String ns = CtsXmlResultReporter.ns;
    static final String BUILD_TAG = "BuildInfo";
    private static final String PHONE_TAG = "PhoneSubInfo";
    private static final String SCREEN_TAG = "Screen";

    private static final String FEATURE_INFO_TAG = "FeatureInfo";
    private static final String FEATURE_TAG = "Feature";
    private static final String FEATURE_ATTR_DELIM = ":";
    private static final String FEATURE_DELIM = ";";

    private static final String OPENGL_TEXTURE_FORMATS_INFO_TAG =
            "OpenGLCompressedTextureFormatsInfo";
    private static final String OPENGL_TEXTURE_FORMAT_TAG = "TextureFormat";
    private static final String OPENGL_TEXTURE_FORMAT_DELIM = ";";

    private static final String OPENGL_EXTENSIONS_TAG = "OpenGlExtensions";
    private static final String OPENGL_EXTENSION_TAG = "OpenGlExtension";
    private static final String OPENGL_EXTENSION_DELIM = ";";

    private static final String SYSLIB_INFO_TAG = "SystemLibrariesInfo";
    private static final String SYSLIB_TAG = "Library";
    private static final String SYSLIB_DELIM = ";";

    private static final String PROCESS_INFO_TAG = "ProcessInfo";
    private static final String PROCESS_TAG = "Process";
    private static final String PROCESS_DELIM = ";";
    private static final String PROCESS_ATTR_DELIM = ":";

    private Map<String, String> mMetrics = new HashMap<String, String>();

    /**
     * Serialize this object and all its contents to XML.
     *
     * @param serializer
     * @throws IOException
     */
    public void serialize(KXmlSerializer serializer) throws IOException {
        serializer.startTag(ns, TAG);

        if (mMetrics.isEmpty()) {
            // this might be expected, if device info collection was turned off
            CLog.d("Could not find device info");
            serializer.endTag(ns, TAG);
            return;
        }

        // Extract metrics that need extra handling, and then dump the remainder into BuildInfo
        Map<String, String> metricsCopy = new HashMap<String, String>(mMetrics);
        serializer.startTag(ns, SCREEN_TAG);
        serializer.attribute(ns, DeviceInfoConstants.RESOLUTION,
                getMetric(metricsCopy, DeviceInfoConstants.RESOLUTION));
        serializer.attribute(ns, DeviceInfoConstants.SCREEN_DENSITY,
                getMetric(metricsCopy, DeviceInfoConstants.SCREEN_DENSITY));
        serializer.attribute(ns, DeviceInfoConstants.SCREEN_DENSITY_BUCKET,
                getMetric(metricsCopy, DeviceInfoConstants.SCREEN_DENSITY_BUCKET));
        serializer.attribute(ns, DeviceInfoConstants.SCREEN_SIZE,
                getMetric(metricsCopy, DeviceInfoConstants.SCREEN_SIZE));
        serializer.attribute(ns, DeviceInfoConstants.SMALLEST_SCREEN_WIDTH_DP,
                getMetric(metricsCopy, DeviceInfoConstants.SMALLEST_SCREEN_WIDTH_DP));
        serializer.endTag(ns, SCREEN_TAG);

        serializer.startTag(ns, PHONE_TAG);
        serializer.attribute(ns, DeviceInfoConstants.PHONE_NUMBER,
                getMetric(metricsCopy, DeviceInfoConstants.PHONE_NUMBER));
        serializer.endTag(ns, PHONE_TAG);

        String featureData = getMetric(metricsCopy, DeviceInfoConstants.FEATURES);
        String processData = getMetric(metricsCopy, DeviceInfoConstants.PROCESSES);
        String sysLibData = getMetric(metricsCopy, DeviceInfoConstants.SYS_LIBRARIES);
        String textureData = getMetric(metricsCopy,
                DeviceInfoConstants.OPEN_GL_COMPRESSED_TEXTURE_FORMATS);
        String openGlExtensionData = getMetric(metricsCopy,
                DeviceInfoConstants.OPEN_GL_EXTENSIONS);

        // dump the remaining metrics without translation
        serializer.startTag(ns, BUILD_TAG);
        for (Map.Entry<String, String> metricEntry : metricsCopy.entrySet()) {
            serializer.attribute(ns, metricEntry.getKey(), metricEntry.getValue());
        }
        serializer.endTag(ns, BUILD_TAG);

        serializeFeatureInfo(serializer, featureData);
        serializeProcessInfo(serializer, processData);
        serializeSystemLibrariesInfo(serializer, sysLibData);
        serializeOpenGLCompressedTextureFormatsInfo(serializer, textureData);
        serializeOpenGLExtensions(serializer, openGlExtensionData);
        // End
        serializer.endTag(ns, TAG);
    }

    /**
     * Fetch and remove given metric from hashmap.
     *
     * @return the metric value or empty string if it was not present in map.
     */
    private String getMetric(Map<String, String> metrics, String metricName ) {
        String value = metrics.remove(metricName);
        if (value == null) {
            value = "";
        }
        return value;
    }

    private void serializeFeatureInfo(KXmlSerializer serializer, String featureData)
            throws IOException {
        serialize(serializer, FEATURE_INFO_TAG, FEATURE_TAG, FEATURE_DELIM, FEATURE_ATTR_DELIM,
                featureData, "name", "type", "available");
    }

    private void serializeProcessInfo(KXmlSerializer serializer, String rootProcesses)
            throws IOException {
        serialize(serializer, PROCESS_INFO_TAG, PROCESS_TAG, PROCESS_DELIM, PROCESS_ATTR_DELIM,
                rootProcesses, "name", "uid");
    }

    private void serializeOpenGLCompressedTextureFormatsInfo(KXmlSerializer serializer,
            String formats) throws IOException {
        serialize(serializer, OPENGL_TEXTURE_FORMATS_INFO_TAG, OPENGL_TEXTURE_FORMAT_TAG,
                OPENGL_TEXTURE_FORMAT_DELIM, null, formats, "name");
    }

    private void serializeOpenGLExtensions(KXmlSerializer serializer, String extensions)
            throws IOException {
        serialize(serializer, OPENGL_EXTENSIONS_TAG, OPENGL_EXTENSION_TAG,
                OPENGL_EXTENSION_DELIM, null, extensions, "name");
    }

    private void serializeSystemLibrariesInfo(KXmlSerializer serializer, String libs)
            throws IOException {
        serialize(serializer, SYSLIB_INFO_TAG, SYSLIB_TAG, SYSLIB_DELIM, null, libs, "name");
    }

    /**
     * Serializes a XML structure where there is an outer tag with tags inside it.
     *
     * <pre>
     *   Input: value1:value2;value3:value4
     *
     *   Output:
     *   <OuterTag>
     *     <SubTag attr1="value1" attr2="value2" />
     *     <SubTag attr1="value3" attr2="value4" />
     *   </OuterTag>
     * </pre>
     *
     * @param serializer to do it
     * @param tag would be "OuterTag"
     * @param subTag would be "SubTag"
     * @param delim would be ";"
     * @param attrDelim would be ":" in the example but can be null if only one attrName given
     * @param data would be "value1:value2;value3:value4"
     * @param attrNames would be an array with "attr1", "attr2"
     * @throws IOException if there is a problem
     */
    private void serialize(KXmlSerializer serializer, String tag, String subTag,
            String delim, String attrDelim, String data, String... attrNames) throws IOException {
        serializer.startTag(ns, tag);

        if (data == null) {
            data = "";
        }

        String[] values = data.split(delim);
        for (String value : values) {
            if (!value.isEmpty()) {
                String[] attrValues = attrDelim != null ? value.split(attrDelim) : new String[] {value};
                if (attrValues.length == attrNames.length) {
                    serializer.startTag(ns, subTag);
                    for (int i = 0; i < attrNames.length; i++) {
                        serializer.attribute(ns, attrNames[i], attrValues[i]);
                    }
                    serializer.endTag(ns,  subTag);
                }
            }
        }

        serializer.endTag(ns, tag);
    }

    /**
     * Populates this class with package result data parsed from XML.
     *
     * @param parser the {@link XmlPullParser}. Expected to be pointing at start
     *            of a {@link #TAG}
     */
    @Override
    void parse(XmlPullParser parser) throws XmlPullParserException, IOException {
        if (!parser.getName().equals(TAG)) {
            throw new XmlPullParserException(String.format(
                    "invalid XML: Expected %s tag but received %s", TAG, parser.getName()));
        }
        int eventType = parser.getEventType();
        while (eventType != XmlPullParser.END_DOCUMENT) {
            if (eventType == XmlPullParser.START_TAG) {
                if (parser.getName().equals(SCREEN_TAG) ||
                        parser.getName().equals(PHONE_TAG) ||
                        parser.getName().equals(BUILD_TAG)) {
                    addMetricsFromAttributes(parser);
                } else if (parser.getName().equals(FEATURE_INFO_TAG)) {
                    mMetrics.put(DeviceInfoConstants.FEATURES, parseFeatures(parser));
                } else if (parser.getName().equals(PROCESS_INFO_TAG)) {
                    mMetrics.put(DeviceInfoConstants.PROCESSES, parseProcess(parser));
                } else if (parser.getName().equals(SYSLIB_INFO_TAG)) {
                    mMetrics.put(DeviceInfoConstants.SYS_LIBRARIES, parseSystemLibraries(parser));
                } else if (parser.getName().equals(OPENGL_TEXTURE_FORMATS_INFO_TAG)) {
                    mMetrics.put(DeviceInfoConstants.OPEN_GL_COMPRESSED_TEXTURE_FORMATS,
                            parseOpenGLCompressedTextureFormats(parser));
                }
            } else if (eventType == XmlPullParser.END_TAG && parser.getName().equals(TAG)) {
                return;
            }
            eventType = parser.next();
        }
    }

    private String parseFeatures(XmlPullParser parser) throws XmlPullParserException, IOException {
        return parseTag(parser, FEATURE_INFO_TAG, FEATURE_TAG, FEATURE_DELIM, FEATURE_ATTR_DELIM,
                "name", "type", "available");
    }

    private String parseProcess(XmlPullParser parser) throws XmlPullParserException, IOException {
        return parseTag(parser, PROCESS_INFO_TAG, PROCESS_TAG, PROCESS_DELIM,
                PROCESS_ATTR_DELIM, "name", "uid");
    }

    private String parseOpenGLCompressedTextureFormats(XmlPullParser parser)
            throws XmlPullParserException, IOException {
        return parseTag(parser, OPENGL_TEXTURE_FORMATS_INFO_TAG, OPENGL_TEXTURE_FORMAT_TAG,
                OPENGL_TEXTURE_FORMAT_DELIM, null, "name");
    }

    private String parseSystemLibraries(XmlPullParser parser)
            throws XmlPullParserException, IOException {
        return parseTag(parser, SYSLIB_INFO_TAG, SYSLIB_TAG, SYSLIB_DELIM, null, "name");
    }

    /**
     * Converts XML into a flattened string.
     *
     * <pre>
     *   Input:
     *   <OuterTag>
     *     <SubTag attr1="value1" attr2="value2" />
     *     <SubTag attr1="value3" attr2="value4" />
     *   </OuterTag>
     *
     *   Output: value1:value2;value3:value4
     * </pre>
     *
     * @param parser that parses the xml
     * @param tag like "OuterTag"
     * @param subTag like "SubTag"
     * @param delim like ";"
     * @param attrDelim like ":" or null if tehre is only one attribute
     * @param attrNames like "attr1", "attr2"
     * @return flattened string like "value1:value2;value3:value4"
     * @throws XmlPullParserException
     * @throws IOException
     */
    private String parseTag(XmlPullParser parser, String tag, String subTag, String delim,
            String attrDelim, String... attrNames) throws XmlPullParserException, IOException {
        if (!parser.getName().equals(tag)) {
            throw new XmlPullParserException(String.format(
                    "invalid XML: Expected %s tag but received %s", tag,
                    parser.getName()));
        }
        StringBuilder flattened = new StringBuilder();

        for (int eventType = parser.getEventType();
                eventType != XmlPullParser.END_DOCUMENT;
                eventType = parser.next()) {

            if (eventType == XmlPullParser.START_TAG && parser.getName().equals(subTag)) {
                for (int i = 0; i < attrNames.length; i++) {
                    flattened.append(getAttribute(parser, attrNames[i]));
                    if (i + 1 < attrNames.length) {
                        flattened.append(attrDelim);
                    }
                }
                flattened.append(delim);
            } else if (eventType == XmlPullParser.END_TAG && parser.getName().equals(tag)) {
                break;
            }
        }

        return flattened.toString();
    }

    /**
     * Adds all attributes from the current XML tag to metrics as name-value pairs
     */
    private void addMetricsFromAttributes(XmlPullParser parser) {
        int attrCount = parser.getAttributeCount();
        for (int i = 0; i < attrCount; i++) {
            mMetrics.put(parser.getAttributeName(i), parser.getAttributeValue(i));
        }
    }

    /**
     * Populate the device info metrics with values collected from device.
     * <p/>
     * Check that the provided device info metrics are consistent with the currently stored metrics.
     * If any inconsistencies occur, logs errors and stores error messages in the metrics map
     */
    public void populateMetrics(Map<String, String> metrics) {
        if (mMetrics.isEmpty()) {
            // no special processing needed, no existing metrics
            mMetrics.putAll(metrics);
            return;
        }
        Map<String, String> metricsCopy = new HashMap<String, String>(
                metrics);
        // add values for metrics that might be different across runs
        combineMetrics(metricsCopy, DeviceInfoConstants.PHONE_NUMBER, DeviceInfoConstants.IMSI,
                DeviceInfoConstants.IMSI, DeviceInfoConstants.SERIAL_NUMBER);

        // ensure all the metrics we expect to be identical actually are
        checkMetrics(metricsCopy, DeviceInfoConstants.BUILD_FINGERPRINT,
                DeviceInfoConstants.BUILD_MODEL, DeviceInfoConstants.BUILD_BRAND,
                DeviceInfoConstants.BUILD_MANUFACTURER, DeviceInfoConstants.BUILD_BOARD,
                DeviceInfoConstants.BUILD_DEVICE, DeviceInfoConstants.PRODUCT_NAME,
                DeviceInfoConstants.BUILD_ABI, DeviceInfoConstants.BUILD_ABI2,
                DeviceInfoConstants.BUILD_ABIS, DeviceInfoConstants.BUILD_ABIS_32,
                DeviceInfoConstants.BUILD_ABIS_64, DeviceInfoConstants.SCREEN_SIZE);
    }

    private void combineMetrics(Map<String, String> metrics, String... keysToCombine) {
        for (String combineKey : keysToCombine) {
            String currentKeyValue = mMetrics.get(combineKey);
            String valueToAdd = metrics.remove(combineKey);
            if (valueToAdd != null) {
                if (currentKeyValue == null) {
                    // strange - no existing value. Can occur during unit testing
                    mMetrics.put(combineKey, valueToAdd);
                } else if (!currentKeyValue.equals(valueToAdd)) {
                    // new value! store a comma separated list
                    valueToAdd = String.format("%s,%s", currentKeyValue, valueToAdd);
                    mMetrics.put(combineKey, valueToAdd);
                } else {
                    // ignore, current value is same as existing
                }

            } else {
                CLog.d("Missing metric %s", combineKey);
            }
        }
    }

    private void checkMetrics(Map<String, String> metrics, String... keysToCheck) {
        Set<String> keyCheckSet = new HashSet<String>();
        Collections.addAll(keyCheckSet, keysToCheck);
        for (Map.Entry<String, String> metricEntry : metrics.entrySet()) {
            String currentValue = mMetrics.get(metricEntry.getKey());
            if (keyCheckSet.contains(metricEntry.getKey()) && currentValue != null
                    && !metricEntry.getValue().equals(currentValue)) {
                CLog.e("Inconsistent info collected from devices. "
                        + "Current result has %s='%s', Received '%s'. Are you sharding or " +
                        "resuming a test run across different devices and/or builds?",
                        metricEntry.getKey(), currentValue, metricEntry.getValue());
                mMetrics.put(metricEntry.getKey(),
                        String.format("ERROR: Inconsistent results: %s, %s",
                                metricEntry.getValue(), currentValue));
            } else {
                mMetrics.put(metricEntry.getKey(), metricEntry.getValue());
            }
        }
    }

    /**
     * Return the currently stored metrics.
     * <p/>
     * Exposed for unit testing.
     */
    Map<String, String> getMetrics() {
        return mMetrics;
    }
}
