/*
 * Copyright (C) 2017 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.
 */
#include "ConfigManager.h"

#include "json/json.h"

#include <fstream>
#include <math.h>
#include <assert.h>


static const float kDegreesToRadians = M_PI / 180.0f;


static float normalizeToPlusMinus180degrees(float theta) {
    const float wraps = floor((theta+180.0f) / 360.0f);
    return theta - wraps*360.0f;
}


static bool readChildNodeAsFloat(const char* groupName,
                                 const Json::Value& parentNode,
                                 const char* childName,
                                 float* value) {
    // Must have a place to put the value!
    assert(value);

    Json::Value childNode = parentNode[childName];
    if (!childNode.isNumeric()) {
        printf("Missing or invalid field %s in record %s", childName, groupName);
        return false;
    }

    *value = childNode.asFloat();
    return true;
}


bool ConfigManager::initialize(const char* configFileName)
{
    bool complete = true;

    // Set up a stream to read in the input file
    std::ifstream configStream(configFileName);

    // Parse the stream into JSON objects
    Json::Reader reader;
    Json::Value rootNode;
    bool parseOk = reader.parse(configStream, rootNode, false /* don't need comments */);
    if (!parseOk) {
        printf("Failed to read configuration file %s\n", configFileName);
        printf("%s\n", reader.getFormatedErrorMessages().c_str());
        return false;
    }


    //
    // Read car information
    //
    {
        Json::Value car = rootNode["car"];
        if (!car.isObject()) {
            printf("Invalid configuration format -- we expect a car description\n");
            return false;
        }
        complete &= readChildNodeAsFloat("car", car, "width",       &mCarWidth);
        complete &= readChildNodeAsFloat("car", car, "wheelBase",   &mWheelBase);
        complete &= readChildNodeAsFloat("car", car, "frontExtent", &mFrontExtent);
        complete &= readChildNodeAsFloat("car", car, "rearExtent",  &mRearExtent);
    }


    //
    // Read display layout information
    //
    {
        Json::Value displayArray = rootNode["displays"];
        if (!displayArray.isArray()) {
            printf("Invalid configuration format -- we expect an array of displays\n");
            return false;
        }

        mDisplays.reserve(displayArray.size());
        for (auto&& node : displayArray) {
            DisplayInfo info;
            info.port = node.get("displayPort", 0).asUInt();
            info.function = node.get("function", "").asCString();
            info.frontRangeInCarSpace = node.get("frontRange", -1).asFloat();
            info.rearRangeInCarSpace = node.get("rearRange", -1).asFloat();

            mDisplays.emplace_back(info);
        }
    }


    //
    // Car top view texture properties for top down view
    //
    {
        Json::Value graphicNode = rootNode["graphic"];
        if (!graphicNode.isObject()) {
            printf("Invalid configuration format -- we expect a graphic description\n");
            return false;
        }
        complete &= readChildNodeAsFloat("graphic", graphicNode, "frontPixel", &mCarGraphicFrontPixel);
        complete &= readChildNodeAsFloat("display", graphicNode, "rearPixel",  &mCarGraphicRearPixel);
    }


    //
    // Read camera information
    // NOTE:  Missing positions and angles are not reported, but instead default to zero
    //
    {
        Json::Value cameraArray = rootNode["cameras"];
        if (!cameraArray.isArray()) {
            printf("Invalid configuration format -- we expect an array of cameras\n");
            return false;
        }

        mCameras.reserve(cameraArray.size());
        for (auto&& node: cameraArray) {
            // Get data from the configuration file
            Json::Value nameNode = node.get("cameraId", "MISSING");
            const char *cameraId = nameNode.asCString();

            Json::Value usageNode = node.get("function", "");
            const char *function = usageNode.asCString();

            float yaw   = node.get("yaw", 0).asFloat();
            float pitch = node.get("pitch", 0).asFloat();
            float roll  = node.get("roll", 0).asFloat();
            float hfov  = node.get("hfov", 0).asFloat();
            float vfov  = node.get("vfov", 0).asFloat();
            bool  hflip = node.get("hflip", false).asBool();
            bool  vflip = node.get("vflip", false).asBool();

            // Wrap the direction angles to be in the 180deg to -180deg range
            // Rotate 180 in yaw if necessary to flip the pitch into the +/-90degree range
            pitch = normalizeToPlusMinus180degrees(pitch);
            if (pitch > 90.0f) {
                yaw += 180.0f;
                pitch = 180.0f - pitch;
            }
            if (pitch < -90.0f) {
                yaw += 180.0f;
                pitch = -180.0f + pitch;
            }
            yaw = normalizeToPlusMinus180degrees(yaw);
            roll = normalizeToPlusMinus180degrees(roll);

            // Range check the FOV values to ensure they are postive and less than 180degrees
            if (hfov > 179.0f) {
                printf("Pathological horizontal field of view %f clamped to 179 degrees\n", hfov);
                hfov = 179.0f;
            }
            if (hfov < 1.0f) {
                printf("Pathological horizontal field of view %f clamped to 1 degree\n", hfov);
                hfov = 1.0f;
            }
            if (vfov > 179.0f) {
                printf("Pathological horizontal field of view %f clamped to 179 degrees\n", vfov);
                vfov = 179.0f;
            }
            if (vfov < 1.0f) {
                printf("Pathological horizontal field of view %f clamped to 1 degree\n", vfov);
                vfov = 1.0f;
            }

            // Store the camera info (converting degrees to radians in the process)
            CameraInfo info;
            info.position[0] = node.get("x", 0).asFloat();
            info.position[1] = node.get("y", 0).asFloat();
            info.position[2] = node.get("z", 0).asFloat();
            info.yaw         = yaw   * kDegreesToRadians;
            info.pitch       = pitch * kDegreesToRadians;
            info.roll        = roll  * kDegreesToRadians;
            info.hfov        = hfov  * kDegreesToRadians;
            info.vfov        = vfov  * kDegreesToRadians;
            info.hflip       = hflip;
            info.vflip       = vflip;
            info.cameraId    = cameraId;
            info.function    = function;

            mCameras.emplace_back(info);
        }
    }

    // If we got this far, we were successful as long as we found all our child fields
    return complete;
}
