import argparse
import dataclasses
from typing import List
import os

os.environ["OPENCV_IO_ENABLE_OPENEXR"]="1"
import numpy as np
from pypsdr.common import gen_cameras
from pypsdr.optimize import Camera, gen_camera_positions
import gin
from pypsdr.utils.io import imwrite, mkdir
from pypsdr.validate import RenderOptions, Scene
import psdr_cpu
import os
from pypsdr.render import render_save_multi_views
from random import seed

@gin.configurable
# generate the constructor
@dataclasses.dataclass
class PreprocessRunner:
    scene_file: str
    batch_size: int = 1
    radius: float = 1.0
    out_dir: str = "./"
    hemisphere: bool = True
    integrator: psdr_cpu.Integrator = psdr_cpu.Direct()
    camera_info: Camera = Camera()

    def run(self):
        psdr_cpu.set_verbose(True)
        self.scene = Scene(self.scene_file)
        self.width = self.scene.camera.width
        self.height = self.scene.camera.height
        self.fov = self.scene.camera.fov
        with gin.config_scope('tar'):
            self.options = RenderOptions(gin.REQUIRED)
        camera_positions = gen_camera_positions(
            batch=self.batch_size, radius=self.radius, hemisphere=True)
        for c in camera_positions:
            c += self.camera_info.target
        cameras = gen_cameras(positions=camera_positions,
                              target=self.camera_info.target,
                              up=self.camera_info.up,
                              fov=self.camera_info.fov,
                              resolution=[self.width, self.height],
                              type=0)
        # cameras[0] = self.scene.camera
        mkdir(self.out_dir)
        np.savetxt(os.path.join(self.out_dir, "cam_pos.txt"), camera_positions)
        mkdir(os.path.join(self.out_dir, "target"))
        render_save_multi_views(self.scene, cameras, self.options,
                                self.integrator, os.path.join(self.out_dir, "target"))


if __name__ == "__main__":
    seed(13)
    default_config = './bunny_in_cbox.conf'
    parser = argparse.ArgumentParser(
        description='Script for generating validation results')
    parser.add_argument('config_file', metavar='config_file',
                        type=str, nargs='?', default=default_config, help='config file')
    args, unknown = parser.parse_known_args()
    # Dependency injection: Arguments are injected into the function from the gin config file.
    gin.parse_config_file(args.config_file, skip_unknown=True)
    runner = PreprocessRunner()
    runner.run()
