/*
 * Copyright (C) 2020 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.server.wifi;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.Log;

import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil;
import com.android.server.wifi.util.XmlUtil;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

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

/**
 * This class performs serialization and parsing of XML data block that contain the map of IMSI
 * protection exemption user approval info.
 */
public class ImsiPrivacyProtectionExemptionStoreData implements WifiConfigStore.StoreData {
    private static final String TAG = "ImsiPrivacyProtectionExemptionStoreData";
    private static final String XML_TAG_SECTION_HEADER_IMSI_PROTECTION_EXEMPTION_CARRIER_MAP =
            "ImsiPrivacyProtectionExemptionMap";
    private static final String XML_TAG_CARRIER_EXEMPTION_MAP = "CarrierExemptionMap";

    /**
     * Interface define the data source for the carrier IMSI protection exemption map store data.
     */
    public interface DataSource {
        /**
         * Retrieve the IMSI protection exemption map from the data source to serialize to disk.
         *
         * @return Map of carrier Id to if allowed.
         */
        Map<Integer, Boolean> toSerialize();

        /**
         * Set the IMSI protection exemption map in the data source after serializing them from disk
         *
         * @param imsiProtectionExemptionMap Map of carrier Id to allowed or not.
         */
        void fromDeserialized(Map<Integer, Boolean> imsiProtectionExemptionMap);

        /**
         * Clear internal data structure in preparation for user switch or initial store read.
         */
        void reset();

        /**
         * Indicates whether there is new data to serialize.
         */
        boolean hasNewDataToSerialize();
    }

    private final DataSource mDataSource;

    /**
     * Set the data source fot store data.
     */
    public ImsiPrivacyProtectionExemptionStoreData(@NonNull DataSource dataSource) {
        mDataSource = dataSource;
    }

    @Override
    public void serializeData(XmlSerializer out, WifiConfigStoreEncryptionUtil encryptionUtil)
            throws XmlPullParserException, IOException {
        Map<String, Boolean> dataToSerialize = integerMapToStringMap(mDataSource.toSerialize());
        XmlUtil.writeNextValue(out, XML_TAG_CARRIER_EXEMPTION_MAP, dataToSerialize);
    }

    @Override
    public void deserializeData(XmlPullParser in, int outerTagDepth, int version,
            WifiConfigStoreEncryptionUtil encryptionUtil)
            throws XmlPullParserException, IOException {
        // Ignore empty reads.
        if (in == null) {
            mDataSource.fromDeserialized(Collections.emptyMap());
            return;
        }

        mDataSource.fromDeserialized(parseCarrierImsiProtectionExemptionMap(in, outerTagDepth,
                version, encryptionUtil));

    }

    private Map<Integer, Boolean> parseCarrierImsiProtectionExemptionMap(XmlPullParser in,
            int outerTagDepth,
            @WifiConfigStore.Version int version,
            @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)
            throws XmlPullParserException, IOException {
        Map<String, Boolean> protectionExemptionMap = new HashMap<>();
        while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
            String[] valueName = new String[1];
            Object value = XmlUtil.readCurrentValue(in, valueName);
            if (valueName[0] == null) {
                throw new XmlPullParserException("Missing value name");
            }
            switch (valueName[0]) {
                case XML_TAG_CARRIER_EXEMPTION_MAP:
                    if (value instanceof Map) {
                        protectionExemptionMap = (Map<String, Boolean>) value;
                    }
                    break;
                default:
                    Log.w(TAG, "Unknown tag under "
                            + XML_TAG_SECTION_HEADER_IMSI_PROTECTION_EXEMPTION_CARRIER_MAP
                            + ": " + valueName[0]);
                    break;
            }
        }
        return stringMapToIntegerMap(protectionExemptionMap);
    }

    private Map<String, Boolean> integerMapToStringMap(Map<Integer, Boolean> input) {
        Map<String, Boolean> output = new HashMap<>();
        if (input == null) {
            return output;
        }
        for (Map.Entry<Integer, Boolean> entry : input.entrySet()) {
            output.put(Integer.toString(entry.getKey()), entry.getValue());
        }
        return output;
    }

    private Map<Integer, Boolean> stringMapToIntegerMap(Map<String, Boolean> input) {
        Map<Integer, Boolean> output = new HashMap<>();
        if (input == null) {
            return output;
        }
        for (Map.Entry<String, Boolean> entry : input.entrySet()) {
            try {
                output.put(Integer.valueOf(entry.getKey()), entry.getValue());
            } catch (NumberFormatException e) {
                Log.e(TAG, "Failed to Integer convert: " + entry.getKey());
            }
        }
        return output;
    }


    @Override
    public void resetData() {
        mDataSource.reset();
    }

    @Override
    public boolean hasNewDataToSerialize() {
        return mDataSource.hasNewDataToSerialize();
    }

    @Override
    public String getName() {
        return XML_TAG_SECTION_HEADER_IMSI_PROTECTION_EXEMPTION_CARRIER_MAP;
    }

    @Override
    public int getStoreFileId() {
        // User general store.
        return WifiConfigStore.STORE_FILE_USER_GENERAL;
    }
}
