#include "tim_helper.hpp"
#include <stdio.hpp>

namespace JabyEngine {
    namespace FileProcessor {
        using GPU::AreaU16;
        using GPU::PositionU16;
        using GPU::SizeU16;

        namespace {
            struct SimpleTIMSize : private SimpleTIM {
                constexpr SimpleTIMSize() {
                }

                constexpr uint16_t get_texture_width() const {
                    return SimpleTIM::get_texture_x();
                }

                constexpr uint16_t get_texture_height() const {
                    return SimpleTIM::get_texture_y();
                }

                constexpr SizeU16 get_texture_size() const {
                    return {SimpleTIMSize::get_texture_width(), SimpleTIMSize::get_texture_height()};
                }

                constexpr uint16_t get_clut_width() const {
                    return SimpleTIM::get_clut_x();
                }

                constexpr uint16_t get_clut_height() const {
                    return SimpleTIM::get_clut_y();
                }
                
                constexpr SizeU16 get_clut_size() const {
                    return {SimpleTIMSize::get_clut_width(), SimpleTIMSize::get_clut_height()};
                }
            };

            struct SimpleTIMState : public TIMFileProcessor::GenericTIM {
                static SimpleTIMState create(const SimpleTIM& dst_info) {
                    SimpleTIMState state;

                    state.tex_area  = AreaU16::create(dst_info.get_texture_position(), SizeU16::create(0, 0));
                    state.clut_area = AreaU16::create(dst_info.get_clut_position(),    SizeU16::create(0, 0));
                    state.words_left = 0;
                    return state;
                }

                virtual Progress parse_header(State::CDDataProcessor& data_proc) override {
                    if(data_proc.data_bytes >= sizeof(SimpleTIMSize)) {
                        const auto size_info = data_proc.simple_read_r<SimpleTIMSize>();
                        
                        this->clut_area.size = size_info.get_clut_size();
                        this->tex_area.size  = size_info.get_texture_size();
                        return Progress::Done;
                    }
                    
                    return Progress::InProgress;
                }

                virtual Progress pre_data_parsing(State::CDDataProcessor& data_proc) {
                    return Progress::Done;
                }
            };
        }

        State create(const uint32_t* data_adr, const SimpleTIM& file) {
            using Callback = Progress(*)(State::CDDataProcessor& data_proc, SimpleTIMState& simple_tim);
            return State::from(SimpleTIMState::create(file), data_adr, reinterpret_cast<Callback>(TIMFileProcessor::parse_header));
        }
    }
}