/*
 * Copyright (C) 2018 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.
 */

#ifndef ANDROID_SERVERS_DISTORTIONMAPPER_H
#define ANDROID_SERVERS_DISTORTIONMAPPER_H

#include <utils/Errors.h>
#include <array>
#include <mutex>

#include "camera/CameraMetadata.h"

namespace android {

namespace camera3 {

/**
 * Utilities to transform between raw (distorted) and warped (corrected) coordinate systems
 * for cameras that support geometric distortion
 */
class DistortionMapper {
  public:
    DistortionMapper();

    /**
     * Check whether distortion correction is supported by the camera HAL
     */
    static bool isDistortionSupported(const CameraMetadata &deviceInfo);

    /**
     * Update static lens calibration info from camera characteristics
     */
    status_t setupStaticInfo(const CameraMetadata &deviceInfo);

    /**
     * Return whether distortion correction can be applied currently
     */
    bool calibrationValid() const;

    /**
     * Correct capture request if distortion correction is enabled
     */
    status_t correctCaptureRequest(CameraMetadata *request);

    /**
     * Correct capture result if distortion correction is enabled
     */
    status_t correctCaptureResult(CameraMetadata *request);


  public: // Visible for testing. Not guarded by mutex; do not use concurrently
    /**
     * Update lens calibration from capture results or equivalent
     */
    status_t updateCalibration(const CameraMetadata &result);

    /**
     * Transform from distorted (original) to corrected (warped) coordinates.
     * Coordinates are transformed in-place
     *
     *   coordPairs: A pointer to an array of consecutive (x,y) points
     *   coordCount: Number of (x,y) pairs to transform
     */
    status_t mapRawToCorrected(int32_t *coordPairs, int coordCount);

    /**
     * Transform from distorted (original) to corrected (warped) coordinates.
     * Coordinates are transformed in-place
     *
     *   rects: A pointer to an array of consecutive (x,y, w, h) rectangles
     *   rectCount: Number of rectangles to transform
     */
    status_t mapRawRectToCorrected(int32_t *rects, int rectCount);

    /**
     * Transform from corrected (warped) to distorted (original) coordinates.
     * Coordinates are transformed in-place
     *
     *   coordPairs: A pointer to an array of consecutive (x,y) points
     *   coordCount: Number of (x,y) pairs to transform
     */
    template<typename T>
    status_t mapCorrectedToRaw(T* coordPairs, int coordCount) const;

    /**
     * Transform from corrected (warped) to distorted (original) coordinates.
     * Coordinates are transformed in-place
     *
     *   rects: A pointer to an array of consecutive (x,y, w, h) rectangles
     *   rectCount: Number of rectangles to transform
     */
    status_t mapCorrectedRectToRaw(int32_t *rects, int rectCount) const;

    struct GridQuad {
        // Source grid quad, or null
        const GridQuad *src;
        // x,y coordinates of corners, in
        // clockwise order
        std::array<float, 8> coords;
    };

    // Find which grid quad encloses the point; returns null if none do
    static const GridQuad* findEnclosingQuad(
            const int32_t pt[2], const std::vector<GridQuad>& grid);

    // Calculate 'horizontal' interpolation coordinate for the point and the quad
    // Assumes the point P is within the quad Q.
    // Given quad with points P1-P4, and edges E12-E41, and considering the edge segments as
    // functions of U: E12(u), where E12(0) = P1 and E12(1) = P2, then we want to find a u
    // such that the edge E12(u) -> E43(u) contains point P.
    // This can be determined by checking if the cross product of vector [E12(u)-E43(u)] and
    // vector [E12(u)-P] is zero. Solving the equation
    // [E12(u)-E43(u)] x [E12(u)-P] = 0 gives a quadratic equation in u; the solution in the range
    // 0 to 1 is the one chosen.
    // If calculateU is true, then an interpolation coordinate for edges E12 and E43 is found;
    // if it is false, then an interpolation coordinate for edges E14 and E23 is found.
    static float calculateUorV(const int32_t pt[2], const GridQuad& quad, bool calculateU);

  private:
    mutable std::mutex mMutex;

    // Number of quads in each dimension of the mapping grids
    constexpr static size_t kGridSize = 15;
    // Margin to expand the grid by to ensure it doesn't clip the domain
    constexpr static float kGridMargin = 0.05f;
    // Fuzziness for float inequality tests
    constexpr static float kFloatFuzz = 1e-4;

    // Metadata key lists to correct

    // Both capture request and result
    static const std::array<uint32_t, 3> kMeteringRegionsToCorrect;

    // Only capture request
    static const std::array<uint32_t, 1> kRequestRectsToCorrect;

    // Only capture result
    static const std::array<uint32_t, 1> kResultRectsToCorrect;

    // Only for capture results
    static const std::array<uint32_t, 2> kResultPointsToCorrect;

    // Utility to create reverse mapping grids
    status_t buildGrids();


    bool mValidMapping;
    bool mValidGrids;

    // intrisic parameters, in pixels
    float mFx, mFy, mCx, mCy, mS;
    // pre-calculated inverses for speed
    float mInvFx, mInvFy;
    // radial/tangential distortion parameters
    float mK[5];

    // pre-correction active array dimensions
    int mArrayWidth, mArrayHeight;
    // active array dimensions
    int mActiveWidth, mActiveHeight;

    std::vector<GridQuad> mCorrectedGrid;
    std::vector<GridQuad> mDistortedGrid;

}; // class DistortionMapper

} // namespace camera3

} // namespace android

#endif
