1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::marker::PhantomData;

use crate::{
    environment::Environment,
    error::Error,
    kernel::Kernel,
    render::{
        settings::{RendererSettings, WgpuSettings},
        Renderer,
    },
    style::Style,
    window::{HeadedMapWindow, MapWindow, MapWindowConfig},
};

pub struct RendererBuilder {
    wgpu_settings: Option<WgpuSettings>,
    renderer_settings: Option<RendererSettings>,
}

impl RendererBuilder {
    pub fn new() -> Self {
        Self {
            wgpu_settings: None,
            renderer_settings: None,
        }
    }

    pub fn with_renderer_settings(mut self, renderer_settings: RendererSettings) -> Self {
        self.renderer_settings = Some(renderer_settings);
        self
    }

    pub fn with_wgpu_settings(mut self, wgpu_settings: WgpuSettings) -> Self {
        self.wgpu_settings = Some(wgpu_settings);
        self
    }

    pub fn build(self) -> UninitializedRenderer {
        UninitializedRenderer {
            wgpu_settings: self.wgpu_settings.unwrap_or_default(),
            renderer_settings: self.renderer_settings.unwrap_or_default(),
        }
    }
}

pub enum InitializationResult {
    Initialized(InitializedRenderer),
    Uninizalized(UninitializedRenderer),
    Gone,
}

impl Default for InitializationResult {
    fn default() -> Self {
        Self::Gone
    }
}

impl InitializationResult {
    pub fn unwarp_renderer(self) -> InitializedRenderer {
        match self {
            InitializationResult::Initialized(renderer) => renderer,
            InitializationResult::Uninizalized(_) => panic!("Renderer is not initialized"),
            InitializationResult::Gone => panic!("Initialization context is gone"),
        }
    }

    pub fn into_option(self) -> Option<Renderer> {
        match self {
            InitializationResult::Initialized(InitializedRenderer { renderer, .. }) => {
                Some(renderer)
            }
            InitializationResult::Uninizalized(_) => None,
            InitializationResult::Gone => panic!("Initialization context is gone"),
        }
    }
}

pub struct UninitializedRenderer {
    pub wgpu_settings: WgpuSettings,
    pub renderer_settings: RendererSettings,
}

impl UninitializedRenderer {
    /// Initializes the whole rendering pipeline for the given configuration.
    /// Returns the initialized map, ready to be run.
    pub async fn initialize_renderer<MWC>(
        self,
        existing_window: &MWC::MapWindow,
    ) -> Result<InitializationResult, Error>
    where
        MWC: MapWindowConfig,
        <MWC as MapWindowConfig>::MapWindow: HeadedMapWindow,
    {
        let renderer = Renderer::initialize(
            existing_window,
            self.wgpu_settings.clone(),
            self.renderer_settings.clone(),
        )
        .await?;
        Ok(InitializationResult::Initialized(InitializedRenderer {
            renderer,
        }))
    }
}

#[cfg(feature = "headless")]
impl UninitializedRenderer {
    pub(crate) async fn initialize_headless<MWC>(
        self,
        existing_window: &MWC::MapWindow,
    ) -> Result<Renderer, Error>
    where
        MWC: MapWindowConfig,
    {
        Ok(Renderer::initialize_headless(
            existing_window,
            self.wgpu_settings.clone(),
            self.renderer_settings.clone(),
        )
        .await?)
    }
}

pub struct InitializedRenderer {
    pub renderer: Renderer,
}