/*
 * Copyright (C) 2016 Google, Inc.
 *
 * 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 <cassert>
#include <cmath>
#include <cstring>
#include <array>
#include <unordered_map>

#include "Helpers.h"
#include "Meshes.h"

namespace {

class Mesh {
  public:
    struct Position {
        float x;
        float y;
        float z;
    };

    struct Normal {
        float x;
        float y;
        float z;
    };

    struct Face {
        int v0;
        int v1;
        int v2;
    };

    static uint32_t vertex_stride() {
        // Position + Normal
        const int comp_count = 6;

        return sizeof(float) * comp_count;
    }

    static VkVertexInputBindingDescription vertex_input_binding() {
        VkVertexInputBindingDescription vi_binding = {};
        vi_binding.binding = 0;
        vi_binding.stride = vertex_stride();
        vi_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;

        return vi_binding;
    }

    static std::vector<VkVertexInputAttributeDescription> vertex_input_attributes() {
        std::vector<VkVertexInputAttributeDescription> vi_attrs(2);
        // Position
        vi_attrs[0].location = 0;
        vi_attrs[0].binding = 0;
        vi_attrs[0].format = VK_FORMAT_R32G32B32_SFLOAT;
        vi_attrs[0].offset = 0;
        // Normal
        vi_attrs[1].location = 1;
        vi_attrs[1].binding = 0;
        vi_attrs[1].format = VK_FORMAT_R32G32B32_SFLOAT;
        vi_attrs[1].offset = sizeof(float) * 3;

        return vi_attrs;
    }

    static VkIndexType index_type() { return VK_INDEX_TYPE_UINT32; }

    static VkPipelineInputAssemblyStateCreateInfo input_assembly_state() {
        VkPipelineInputAssemblyStateCreateInfo ia_info = {};
        ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
        ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
        ia_info.primitiveRestartEnable = false;
        return ia_info;
    }

    void build(const std::vector<std::array<float, 6>> &vertices, const std::vector<std::array<int, 3>> &faces) {
        positions_.reserve(vertices.size());
        normals_.reserve(vertices.size());
        for (const auto &v : vertices) {
            positions_.emplace_back(Position{v[0], v[1], v[2]});
            normals_.emplace_back(Normal{v[3], v[4], v[5]});
        }

        faces_.reserve(faces.size());
        for (const auto &f : faces)
            faces_.emplace_back(Face{f[0], f[1], f[2]});
    }

    uint32_t vertex_count() const { return static_cast<uint32_t>(positions_.size()); }

    VkDeviceSize vertex_buffer_size() const { return vertex_stride() * vertex_count(); }

    void vertex_buffer_write(void *data) const {
        float *dst = reinterpret_cast<float *>(data);
        for (size_t i = 0; i < positions_.size(); i++) {
            const Position &pos = positions_[i];
            const Normal &normal = normals_[i];
            dst[0] = pos.x;
            dst[1] = pos.y;
            dst[2] = pos.z;
            dst[3] = normal.x;
            dst[4] = normal.y;
            dst[5] = normal.z;
            dst += 6;
        }
    }

    uint32_t index_count() const { return static_cast<uint32_t>(faces_.size()) * 3; }

    VkDeviceSize index_buffer_size() const { return sizeof(uint32_t) * index_count(); }

    void index_buffer_write(void *data) const {
        uint32_t *dst = reinterpret_cast<uint32_t *>(data);
        for (const auto &face : faces_) {
            dst[0] = face.v0;
            dst[1] = face.v1;
            dst[2] = face.v2;
            dst += 3;
        }
    }

    std::vector<Position> positions_;
    std::vector<Normal> normals_;
    std::vector<Face> faces_;
};

class BuildPyramid {
  public:
    BuildPyramid(Mesh &mesh) {
        const std::vector<std::array<float, 6>> vertices = {
            //      position                normal
            {{0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f}},     {{-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}},
            {{1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f}}, {{1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f}},
            {{-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f}},
        };

        const std::vector<std::array<int, 3>> faces = {
            {{0, 1, 2}}, {{0, 2, 3}}, {{0, 3, 4}}, {{0, 4, 1}}, {{1, 4, 3}}, {{1, 3, 2}},
        };

        mesh.build(vertices, faces);
    }
};

class BuildIcosphere {
  public:
    BuildIcosphere(Mesh &mesh) : mesh_(mesh), radius_(1.0f) {
        const int tessellate_level = 2;

        build_icosahedron();
        for (int i = 0; i < tessellate_level; i++)
            tessellate();
    }

  private:
    void build_icosahedron() {
        // https://en.wikipedia.org/wiki/Regular_icosahedron
        const float l1 = std::sqrt(2.0f / (5.0f + std::sqrt(5.0f))) * radius_;
        const float l2 = std::sqrt(2.0f / (5.0f - std::sqrt(5.0f))) * radius_;
        // vertices are from three golden rectangles
        const std::vector<std::array<float, 6>> icosahedron_vertices = {
            //   position           normal
            {{
                -l1, -l2, 0.0f, -l1, -l2, 0.0f,
            }},
            {{
                l1, -l2, 0.0f, l1, -l2, 0.0f,
            }},
            {{
                l1, l2, 0.0f, l1, l2, 0.0f,
            }},
            {{
                -l1, l2, 0.0f, -l1, l2, 0.0f,
            }},

            {{
                -l2, 0.0f, -l1, -l2, 0.0f, -l1,
            }},
            {{
                l2, 0.0f, -l1, l2, 0.0f, -l1,
            }},
            {{
                l2, 0.0f, l1, l2, 0.0f, l1,
            }},
            {{
                -l2, 0.0f, l1, -l2, 0.0f, l1,
            }},

            {{
                0.0f, -l1, -l2, 0.0f, -l1, -l2,
            }},
            {{
                0.0f, l1, -l2, 0.0f, l1, -l2,
            }},
            {{
                0.0f, l1, l2, 0.0f, l1, l2,
            }},
            {{
                0.0f, -l1, l2, 0.0f, -l1, l2,
            }},
        };
        const std::vector<std::array<int, 3>> icosahedron_faces = {
            // triangles sharing vertex 0
            {{0, 1, 11}},
            {{0, 11, 7}},
            {{0, 7, 4}},
            {{0, 4, 8}},
            {{0, 8, 1}},
            // adjacent triangles
            {{11, 1, 6}},
            {{7, 11, 10}},
            {{4, 7, 3}},
            {{8, 4, 9}},
            {{1, 8, 5}},
            // triangles sharing vertex 2
            {{2, 3, 10}},
            {{2, 10, 6}},
            {{2, 6, 5}},
            {{2, 5, 9}},
            {{2, 9, 3}},
            // adjacent triangles
            {{10, 3, 7}},
            {{6, 10, 11}},
            {{5, 6, 1}},
            {{9, 5, 8}},
            {{3, 9, 4}},
        };

        mesh_.build(icosahedron_vertices, icosahedron_faces);
    }

    void tessellate() {
        size_t middle_point_count = mesh_.faces_.size() * 3 / 2;
        size_t final_face_count = mesh_.faces_.size() * 4;

        std::vector<Mesh::Face> faces;
        faces.reserve(final_face_count);

        middle_points_.clear();
        middle_points_.reserve(middle_point_count);

        mesh_.positions_.reserve(mesh_.vertex_count() + middle_point_count);
        mesh_.normals_.reserve(mesh_.vertex_count() + middle_point_count);

        for (const auto &f : mesh_.faces_) {
            int v0 = f.v0;
            int v1 = f.v1;
            int v2 = f.v2;

            int v01 = add_middle_point(v0, v1);
            int v12 = add_middle_point(v1, v2);
            int v20 = add_middle_point(v2, v0);

            faces.emplace_back(Mesh::Face{v0, v01, v20});
            faces.emplace_back(Mesh::Face{v1, v12, v01});
            faces.emplace_back(Mesh::Face{v2, v20, v12});
            faces.emplace_back(Mesh::Face{v01, v12, v20});
        }

        mesh_.faces_.swap(faces);
    }

    int add_middle_point(int a, int b) {
        uint64_t key = (a < b) ? ((uint64_t)a << 32 | b) : ((uint64_t)b << 32 | a);
        auto it = middle_points_.find(key);
        if (it != middle_points_.end())
            return it->second;

        const Mesh::Position &pos_a = mesh_.positions_[a];
        const Mesh::Position &pos_b = mesh_.positions_[b];
        Mesh::Position pos_mid = {
            (pos_a.x + pos_b.x) / 2.0f, (pos_a.y + pos_b.y) / 2.0f, (pos_a.z + pos_b.z) / 2.0f,
        };
        float scale = radius_ / std::sqrt(pos_mid.x * pos_mid.x + pos_mid.y * pos_mid.y + pos_mid.z * pos_mid.z);
        pos_mid.x *= scale;
        pos_mid.y *= scale;
        pos_mid.z *= scale;

        Mesh::Normal normal_mid = {pos_mid.x, pos_mid.y, pos_mid.z};
        normal_mid.x /= radius_;
        normal_mid.y /= radius_;
        normal_mid.z /= radius_;

        mesh_.positions_.emplace_back(pos_mid);
        mesh_.normals_.emplace_back(normal_mid);

        int mid = mesh_.vertex_count() - 1;
        middle_points_.emplace(std::make_pair(key, mid));

        return mid;
    }

    Mesh &mesh_;
    const float radius_;
    std::unordered_map<uint64_t, uint32_t> middle_points_;
};

class BuildTeapot {
  public:
    BuildTeapot(Mesh &mesh) {
#include "Meshes.teapot.h"
        const int position_count = sizeof(teapot_positions) / sizeof(teapot_positions[0]);
        const int index_count = sizeof(teapot_indices) / sizeof(teapot_indices[0]);
        assert(position_count % 3 == 0 && index_count % 3 == 0);

        Mesh::Position translate;
        float scale;
        get_transform(teapot_positions, position_count, translate, scale);

        for (int i = 0; i < position_count; i += 3) {
            mesh.positions_.emplace_back(Mesh::Position{
                (teapot_positions[i + 0] + translate.x) * scale, (teapot_positions[i + 1] + translate.y) * scale,
                (teapot_positions[i + 2] + translate.z) * scale,
            });

            mesh.normals_.emplace_back(Mesh::Normal{
                teapot_normals[i + 0], teapot_normals[i + 1], teapot_normals[i + 2],
            });
        }

        for (int i = 0; i < index_count; i += 3) {
            mesh.faces_.emplace_back(Mesh::Face{teapot_indices[i + 0], teapot_indices[i + 1], teapot_indices[i + 2]});
        }
    }

    void get_transform(const float *positions, int position_count, Mesh::Position &translate, float &scale) {
        float min[3] = {
            positions[0], positions[1], positions[2],
        };
        float max[3] = {
            positions[0], positions[1], positions[2],
        };
        for (int i = 3; i < position_count; i += 3) {
            for (int j = 0; j < 3; j++) {
                if (min[j] > positions[i + j])
                    min[j] = positions[i + j];
                if (max[j] < positions[i + j])
                    max[j] = positions[i + j];
            }
        }

        translate.x = -(min[0] + max[0]) / 2.0f;
        translate.y = -(min[1] + max[1]) / 2.0f;
        translate.z = -(min[2] + max[2]) / 2.0f;

        float extents[3] = {
            max[0] + translate.x, max[1] + translate.y, max[2] + translate.z,
        };

        float max_extent = extents[0];
        if (max_extent < extents[1])
            max_extent = extents[1];
        if (max_extent < extents[2])
            max_extent = extents[2];

        scale = 1.0f / max_extent;
    }
};

void build_meshes(std::array<Mesh, Meshes::MESH_COUNT> &meshes) {
    BuildPyramid build_pyramid(meshes[Meshes::MESH_PYRAMID]);
    BuildIcosphere build_icosphere(meshes[Meshes::MESH_ICOSPHERE]);
    BuildTeapot build_teapot(meshes[Meshes::MESH_TEAPOT]);
}

} // namespace

Meshes::Meshes(VkDevice dev, const std::vector<VkMemoryPropertyFlags> &mem_flags)
    : dev_(dev), vertex_input_binding_(Mesh::vertex_input_binding()), vertex_input_attrs_(Mesh::vertex_input_attributes()),
      vertex_input_state_(), input_assembly_state_(Mesh::input_assembly_state()), index_type_(Mesh::index_type()) {
    vertex_input_state_.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
    vertex_input_state_.vertexBindingDescriptionCount = 1;
    vertex_input_state_.pVertexBindingDescriptions = &vertex_input_binding_;
    vertex_input_state_.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertex_input_attrs_.size());
    vertex_input_state_.pVertexAttributeDescriptions = vertex_input_attrs_.data();

    std::array<Mesh, MESH_COUNT> meshes;
    build_meshes(meshes);

    draw_commands_.reserve(meshes.size());
    uint32_t first_index = 0;
    int32_t vertex_offset = 0;
    VkDeviceSize vb_size = 0;
    VkDeviceSize ib_size = 0;
    for (const auto &mesh : meshes) {
        VkDrawIndexedIndirectCommand draw = {};
        draw.indexCount = mesh.index_count();
        draw.instanceCount = 1;
        draw.firstIndex = first_index;
        draw.vertexOffset = vertex_offset;
        draw.firstInstance = 0;

        draw_commands_.push_back(draw);

        first_index += mesh.index_count();
        vertex_offset += mesh.vertex_count();
        vb_size += mesh.vertex_buffer_size();
        ib_size += mesh.index_buffer_size();
    }

    allocate_resources(vb_size, ib_size, mem_flags);

    uint8_t *vb_data, *ib_data;
    vk::assert_success(vk::MapMemory(dev_, mem_, 0, VK_WHOLE_SIZE, 0, reinterpret_cast<void **>(&vb_data)));
    ib_data = vb_data + ib_mem_offset_;

    for (const auto &mesh : meshes) {
        mesh.vertex_buffer_write(vb_data);
        mesh.index_buffer_write(ib_data);
        vb_data += mesh.vertex_buffer_size();
        ib_data += mesh.index_buffer_size();
    }

    vk::UnmapMemory(dev_, mem_);
}

Meshes::~Meshes() {
    vk::FreeMemory(dev_, mem_, nullptr);
    vk::DestroyBuffer(dev_, vb_, nullptr);
    vk::DestroyBuffer(dev_, ib_, nullptr);
}

void Meshes::cmd_bind_buffers(VkCommandBuffer cmd) const {
    const VkDeviceSize vb_offset = 0;
    vk::CmdBindVertexBuffers(cmd, 0, 1, &vb_, &vb_offset);

    vk::CmdBindIndexBuffer(cmd, ib_, 0, index_type_);
}

void Meshes::cmd_draw(VkCommandBuffer cmd, Type type) const {
    const auto &draw = draw_commands_[type];
    vk::CmdDrawIndexed(cmd, draw.indexCount, draw.instanceCount, draw.firstIndex, draw.vertexOffset, draw.firstInstance);
}

void Meshes::allocate_resources(VkDeviceSize vb_size, VkDeviceSize ib_size, const std::vector<VkMemoryPropertyFlags> &mem_flags) {
    VkBufferCreateInfo buf_info = {};
    buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
    buf_info.size = vb_size;
    buf_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
    buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
    vk::CreateBuffer(dev_, &buf_info, nullptr, &vb_);

    buf_info.size = ib_size;
    buf_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
    vk::CreateBuffer(dev_, &buf_info, nullptr, &ib_);

    VkMemoryRequirements vb_mem_reqs, ib_mem_reqs;
    vk::GetBufferMemoryRequirements(dev_, vb_, &vb_mem_reqs);
    vk::GetBufferMemoryRequirements(dev_, ib_, &ib_mem_reqs);

    // indices follow vertices
    ib_mem_offset_ = vb_mem_reqs.size + (ib_mem_reqs.alignment - (vb_mem_reqs.size % ib_mem_reqs.alignment));

    VkMemoryAllocateInfo mem_info = {};
    mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
    mem_info.allocationSize = ib_mem_offset_ + ib_mem_reqs.size;

    // find any supported and mappable memory type
    uint32_t mem_types = (vb_mem_reqs.memoryTypeBits & ib_mem_reqs.memoryTypeBits);
    for (uint32_t idx = 0; idx < mem_flags.size(); idx++) {
        if ((mem_types & (1 << idx)) && (mem_flags[idx] & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) &&
            (mem_flags[idx] & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
            // TODO this may not be reachable
            mem_info.memoryTypeIndex = idx;
            break;
        }
    }

    vk::AllocateMemory(dev_, &mem_info, nullptr, &mem_);

    vk::BindBufferMemory(dev_, vb_, mem_, 0);
    vk::BindBufferMemory(dev_, ib_, mem_, ib_mem_offset_);
}
