/*
 * Copyright (C) 2016 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.car.hal;

import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_BOOLEAN;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_BYTES;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC2;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC3;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC4;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC3;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_STRING;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_BOOLEAN;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4;
import static com.android.car.vehiclenetwork.VehiclePropValueUtil.getVectorValueType;
import static java.lang.Integer.toHexString;

import android.car.VehicleAreaType;
import android.car.VehicleZoneUtil;
import android.car.hardware.CarPropertyConfig;
import android.car.hardware.CarPropertyValue;

import com.google.protobuf.ByteString;

import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfig;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;

import java.util.List;

/**
 * Utility functions to work with {@link CarPropertyConfig} and {@link CarPropertyValue}
 */
/*package*/ final class CarPropertyUtils {

    /* Utility class has no public constructor */
    private CarPropertyUtils() {}

    /** Converts {@link VehiclePropValue} to {@link CarPropertyValue} */
    static CarPropertyValue<?> toCarPropertyValue(
            VehiclePropValue halValue, int propertyId) {
        Class<?> clazz = getJavaClass(halValue.getValueType());
        int areaId = halValue.getZone();
        if (Boolean.class == clazz) {
            return new CarPropertyValue<>(propertyId, areaId, halValue.getInt32Values(0) == 1);
        } else if (String.class == clazz) {
            return new CarPropertyValue<>(propertyId, areaId, halValue.getStringValue());
        } else if (Long.class == clazz) {
            return new CarPropertyValue<>(propertyId, areaId, halValue.getInt64Value());
        } else if (byte[].class == clazz) {
            byte[] halData = halValue.getBytesValue().toByteArray();
            return new CarPropertyValue<>(propertyId, areaId, halData);
        } else /* All list properties */ {
            Object[] values = getRawValueList(clazz, halValue).toArray();
            return new CarPropertyValue<>(propertyId, areaId,
                    values.length == 1 ? values[0] : values);
        }
    }

    /** Converts {@link CarPropertyValue} to {@link VehiclePropValue} */
    static VehiclePropValue toVehiclePropValue(CarPropertyValue hvacProp, int halPropId) {
        VehiclePropValue.Builder builder = VehiclePropValue.newBuilder();
        builder.setProp(halPropId);

        if (hvacProp.getAreaId() != 0) {
            builder.setZone(hvacProp.getAreaId());
        }

        Object o = hvacProp.getValue();

        boolean hasArea = hvacProp.getAreaId() != 0;
        int vectorLength = (o instanceof Object[] ? ((Object[]) o).length : 0);
        int halType;
        if (o instanceof Boolean) {
            halType = hasArea ? VEHICLE_VALUE_TYPE_ZONED_BOOLEAN : VEHICLE_VALUE_TYPE_BOOLEAN;
            builder.addInt32Values(((Boolean )o) ? 1 : 0);
        } else if (o instanceof Integer) {
            halType = hasArea ? VEHICLE_VALUE_TYPE_ZONED_INT32 : VEHICLE_VALUE_TYPE_INT32;
            builder.addInt32Values((Integer) o);
        } else if (o instanceof Float) {
            halType = hasArea ? VEHICLE_VALUE_TYPE_ZONED_FLOAT : VEHICLE_VALUE_TYPE_FLOAT;
            builder.addFloatValues((Float) o);
        } else if (o instanceof Integer[]) {
            halType = getVectorValueType(
                    hasArea ? VEHICLE_VALUE_TYPE_ZONED_INT32 : VEHICLE_VALUE_TYPE_ZONED_INT32,
                    vectorLength);
            for (Integer i : (Integer[]) o) {
                builder.addInt32Values(i);
            }
        } else if (o instanceof Float[]) {
            halType = getVectorValueType(
                    hasArea ? VEHICLE_VALUE_TYPE_ZONED_FLOAT : VEHICLE_VALUE_TYPE_ZONED_FLOAT,
                    vectorLength);
            for (Float f : (Float[]) o) {
                builder.addFloatValues(f);
            }
        } else if (o instanceof String) {
            halType = VEHICLE_VALUE_TYPE_STRING;
            builder.setStringValue((String) o);
        } else if (o instanceof byte[]) {
            halType = VEHICLE_VALUE_TYPE_BYTES;  // We don't have zoned type in vehicle.h
            builder.setBytesValue(ByteString.copyFrom((byte[]) o));
        } else {
            throw new IllegalArgumentException("Unexpected type in: " + hvacProp);
        }
        builder.setValueType(halType);
        return builder.build();
    }

    /**
     * Converts {@link VehiclePropConfig} to {@link CarPropertyConfig}.
     */
    static CarPropertyConfig<?> toCarPropertyConfig(VehiclePropConfig p, int propertyId) {
        int[] areas = VehicleZoneUtil.listAllZones(p.getZones());

        // TODO: handle other vehicle area types.
        int areaType = areas.length == 0
                ? VehicleAreaType.VEHICLE_AREA_TYPE_NONE : VehicleAreaType.VEHICLE_AREA_TYPE_ZONE;

        Class<?> clazz = getJavaClass(p.getValueType());
        if (clazz == Boolean.class || clazz == byte[].class || clazz == String.class) {
            return CarPropertyConfig
                    .newBuilder(clazz, propertyId, areaType, /* capacity */ 1)
                    .addAreas(areas)
                    .build();
        } else {
            List mins;
            List maxs;
            if (classMatched(Integer.class, clazz)) {
                mins = p.getInt32MinsList();
                maxs = p.getInt32MaxsList();
            } else if (classMatched(Float.class, clazz)) {
                mins = p.getFloatMinsList();
                maxs = p.getFloatMaxsList();
            } else {
                throw new IllegalArgumentException("Unexpected type: " + clazz);
            }
            CarPropertyConfig.Builder builder = CarPropertyConfig
                    .newBuilder(clazz, propertyId, areaType, /* capacity */ mins.size());
            for (int i = 0; i < mins.size(); i++) {
                int areaId = areas.length == 0 ? 0 : areas[i];
                builder.addAreaConfig(areaId, mins.get(i), maxs.get(i));
            }
            return builder.build();
        }
    }

    private static Class<?> getJavaClass(int halType) {
        switch (halType) {
            case VEHICLE_VALUE_TYPE_BOOLEAN:
            case VEHICLE_VALUE_TYPE_ZONED_BOOLEAN:
                return Boolean.class;
            case VEHICLE_VALUE_TYPE_FLOAT:
            case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
                return Float.class;
            case VEHICLE_VALUE_TYPE_INT32:
            case VEHICLE_VALUE_TYPE_ZONED_INT32:
                return Integer.class;
            case VEHICLE_VALUE_TYPE_INT32_VEC2:
            case VEHICLE_VALUE_TYPE_INT32_VEC3:
            case VEHICLE_VALUE_TYPE_INT32_VEC4:
            case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
            case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
            case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4:
                return Integer[].class;
            case VEHICLE_VALUE_TYPE_FLOAT_VEC2:
            case VEHICLE_VALUE_TYPE_FLOAT_VEC3:
            case VEHICLE_VALUE_TYPE_FLOAT_VEC4:
            case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
            case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
            case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4:
                return Float[].class;
            case VEHICLE_VALUE_TYPE_STRING:
                return String.class;
            case VEHICLE_VALUE_TYPE_BYTES:
                return byte[].class;
            default:
                throw new IllegalArgumentException("Unexpected type: " + toHexString(halType));
        }
    }

    private static List getRawValueList(Class<?> clazz, VehiclePropValue vehiclePropValue) {
        if (classMatched(Float.class, clazz)) {
            return vehiclePropValue.getFloatValuesList();
        } else if (classMatched(Integer.class, clazz)) {
            return vehiclePropValue.getInt32ValuesList();
        } else {
            throw new IllegalArgumentException("Unexpected type: " + clazz);
        }
    }

    private static boolean classMatched(Class<?> class1, Class<?> class2) {
        return class1 == class2 || class1.getComponentType() == class2;
    }
}
