/*############################################################################*/
/*#                                                                          #*/
/*#  Some common elements related to the screen                              #*/
/*#                                                                          #*/
/*#                                                                          #*/
/*#  Filename:      ScreenCommon.h                                           #*/
/*#  Version:       0.1                                                      #*/
/*#  Date:          30/10/2020                                               #*/
/*#  Author(s):     Peter Stitt                                              #*/
/*#  Licence:       LGPL + proprietary                                       #*/
/*#                                                                          #*/
/*############################################################################*/

#ifndef SPATIALAUDIO_SCREEN_COMMON_H
#define SPATIALAUDIO_SCREEN_COMMON_H

#include "Coordinates.h"
#include "Tools.h"

namespace spaudio {

    /** Holds a screen with either cartesian or polar coordinates. If isCartesianScreen is set true then
     * the centre should be set in centreCartesianPosition.
     */
    struct Screen {
        // Flag if the screen is cartesian. Only one set of properties is used depending on this flag so make sure they match
        bool isCartesianScreen = false;

        double aspectRatio = 1.78;

        // Polar screen properties
        PolarPosition<double> centrePolarPosition = PolarPosition<double>{ 0.,0.,1. };
        double widthAzimuth = 58.0;

        // Cartesian screen properties
        CartesianPosition<double> centreCartesianPosition;
        double widthX = 0.0;
    };

    /** PolarEdges structure that holds the representation of the screen for
     *  use in the screen edge lock and screen scaling prcocessing classes.
     */
    struct PolarEdges {
        double leftAzimuth = 0.0;
        double rightAzimuth = 0.0;
        double bottomElevation = 0.0;
        double topElevation = 0.0;


        /** Convert from Screen to Polar Edges. See Rec. ITU-R BS.2127-0 Sec. 7.3.3.1 pg. 40.
         * @param screen	The screen from which the PolarEdges are to be calcualted
         */
        void fromScreen(Screen screen)
        {
            CartesianPosition<double> centre;
            CartesianPosition<double> v_x, v_z;
            if (screen.isCartesianScreen)
            {
                double w = screen.widthAzimuth;
                double a = screen.aspectRatio;

                centre = screen.centreCartesianPosition;
                double width = w / 2.;
                double height = width / a;

                v_x = CartesianPosition<double>{ width,0.,0. };
                v_z = CartesianPosition<double>{ 0., 0., height };
            }
            else
            {
                double az = screen.centrePolarPosition.azimuth;
                double el = screen.centrePolarPosition.elevation;
                double d = screen.centrePolarPosition.distance;
                double w = screen.widthAzimuth;
                double a = screen.aspectRatio;

                centre = PolarToCartesian(screen.centrePolarPosition);
                double width = d * std::tan(DEG2RAD * w / 2.);
                double height = width / a;

                double l_xyz[3][3];
                LocalCoordinateSystem(az, el, l_xyz);
                v_x = CartesianPosition<double>{ l_xyz[0][0] * width,l_xyz[0][1] * width,l_xyz[0][2] * width };
                v_z = CartesianPosition<double>{ l_xyz[2][0] * height,l_xyz[2][1] * height,l_xyz[2][2] * height };
            }

            leftAzimuth = CartesianToPolar(centre - v_x).azimuth;
            rightAzimuth = CartesianToPolar(centre + v_x).azimuth;
            bottomElevation = CartesianToPolar(centre - v_z).elevation;
            topElevation = CartesianToPolar(centre + v_z).elevation;
        }
    };

} // namespace spaudio

#endif // SPATIALAUDIO_SCREEN_COMMON_H
