logo
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
use std::future::Future;

use crate::{
    engine::d2,
    foundation::{Key, TargetPlatform},
    services::AssetBundle,
    ui::{Codec, Locale, Size, TextDirection},
};

pub struct ImageConfiguration {
    // The preferred AssetBundle to use if the ImageProvider needs one and does not have one already selected.
    pub bundle: Option<Box<dyn AssetBundle>>,

    // The device pixel ratio where the image will be shown.
    pub device_pixel_ratio: Option<f32>,

    // The language and region for which to select the image.
    pub locale: Option<Locale>,

    // The TargetPlatform for which assets should be used.
    // This allows images to be specified in a platform-neutral fashion yet use different assets on different platforms,
    // to match local conventions e.g. for color matching or shadows.
    pub platform: Option<TargetPlatform>,

    // The size at which the image will be rendered.
    pub size: Option<Size>,

    // The reading direction of the language for which to select the image.
    pub text_direction: Option<TextDirection>,
}

impl Default for ImageConfiguration {
    fn default() -> Self {
        Self {
            bundle: Default::default(),
            device_pixel_ratio: Default::default(),
            locale: Default::default(),
            platform: Default::default(),
            size: Default::default(),
            text_direction: Default::default(),
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct ImageInfo {
    // The raw image pixels.
    pub image: d2::Image,

    // The linear scale factor for drawing this image at its intended size.
    pub scale: f32,

    // The size of raw image pixels in bytes.
    pub size_bytes: i32,
}

impl ImageInfo {
    // Creates an ImageInfo with a cloned image.
    pub fn clone() -> ImageInfo {
        todo!()
    }

    // Disposes of this object.
    pub fn dispose() {}

    // Whether this ImageInfo is a clone of the other.
    pub fn is_clone_of(other: ImageInfo) -> bool {
        todo!()
    }
}

pub struct ImageChunkEvent {
    // The number of bytes that have been received across the wire thus far.
    pub cumulative_bytes_loaded: i32,

    // The expected number of bytes that need to be received to finish loading the image.
    pub expected_total_bytes: Option<i32>,
}

// Fn(ImageChunkEvent event)
pub type ImageChunkListener = dyn FnMut(ImageChunkEvent);

// Fn(image: ImageInfo, synchronous_call: bool)
pub type ImageListener = dyn FnMut(ImageInfo, bool);

#[allow(dead_code)]
pub struct ImageStreamListener {
    // Callback for getting notified when a chunk of bytes has been received during the loading of the image.
    on_chunk: Option<Box<ImageChunkListener>>,

    // Callback for getting notified when an error occurs while loading an image.
    on_error: Option<Box<ImageErrorListener>>,

    // Callback for getting notified that an image is available.
    on_image: Box<ImageListener>,
}

impl ImageStreamListener {
    pub fn new(
        on_image: Box<ImageListener>,
        on_chunk: Option<Box<ImageChunkListener>>,
        on_error: Option<Box<ImageErrorListener>>,
    ) -> Self {
        Self {
            on_chunk,
            on_error,
            on_image,
        }
    }
}

impl Default for ImageStreamListener {
    fn default() -> Self {
        Self {
            on_chunk: Default::default(),
            on_error: Default::default(),
            on_image: box |_, _| {}, // NullObject
        }
    }
}

#[allow(dead_code)]
pub struct ImageStream {
    // The completer that has been assigned to this image stream.
    pub completer: Option<ImageStreamCompleter>,

    // Returns an object which can be used with == to determine if this ImageStream shares the same listeners list as another ImageStream.
    pub key: Key,

    // KISS
    pub image: Option<d2::Image>,
}

impl ImageStream {
    // Adds a listener callback that is called whenever a new concrete ImageInfo object is available.
    // If a concrete image is already available, this object will call the listener synchronously.
    pub fn add_listener(&self, listener: ImageStreamListener) {
        if let Some(image) = self.image {
            let mut handle = listener.on_image;
            handle(
                ImageInfo {
                    image,
                    scale: 1.0,
                    size_bytes: 0,
                },
                true,
            )
        }
    }

    // Stops listening for events from this stream's ImageStreamCompleter.
    pub fn remove_listener(&self, listener: ImageStreamListener) {}

    // Assigns a particular ImageStreamCompleter to this ImageStream.
    pub fn set_completer(&self, value: ImageStreamCompleter) {}
}

impl Default for ImageStream {
    fn default() -> Self {
        Self {
            completer: Default::default(),
            key: Default::default(),
            image: Default::default(),
        }
    }
}

pub struct ImageCacheStatus {
    // An image that has been submitted to ImageCache.putIfAbsent, has completed, fits based on the sizing rules of the cache, and has not been evicted.
    pub keep_alive: bool,

    // An image that has been submitted to ImageCache.putIfAbsent and has at least one listener on its ImageStreamCompleter.
    pub live: bool,

    // An image that has been submitted to ImageCache.putIfAbsent, but not yet completed.
    pub pending: bool,

    // An image that is tracked in some way by the ImageCache, whether pending, keepAlive, or live.
    pub tracked: bool,

    // An image that either has not been submitted to ImageCache.putIfAbsent or has otherwise been evicted from the keepAlive and live caches.
    pub untracked: bool,
}

// impl<T: Default> Default for ImageProvider<T> {
//     fn default() -> Self {
//         Self(Default::default())
//     }
// }

pub struct ImageCache {
    // The current number of cached entries.
    pub current_size: i32,

    // The current size of cached entries in bytes.
    pub current_size_bytes: i32,

    // The number of live images being held by the ImageCache.
    pub live_image_count: i32,

    // Maximum number of entries to store in the cache.
    pub maximum_size: i32,

    // Maximum size of entries to store in the cache in bytes.
    pub maximum_size_bytes: i32,

    // The number of images being tracked as pending in the ImageCache.
    pub pending_image_count: i32,
}

impl ImageCache {
    // Evicts all pending and keepAlive entries from the cache.
    pub fn clear() {}

    // Clears any live references to images in this cache.
    pub fn clear_live_images() {}

    // Returns whether this key has been previously added by putIfAbsent.
    pub fn contains_key(key: Key) -> bool {
        todo!()
    }

    // Evicts a single entry from the cache, returning true if successful.
    pub fn evict(key: Key, include_live: bool /* = true*/) -> bool {
        todo!()
    }

    // Returns the previously cached ImageStream for the given key, if available;
    // if not, calls the given callback to obtain it first. In either case, the key is moved to the 'most recently used' position.
    pub fn put_if_absent(
        key: Key,
        loader: ImageStreamCompleter,
        on_error: Option<Box<ImageErrorListener>>,
    ) -> Option<ImageStreamCompleter> {
        todo!()
    }

    // The ImageCacheStatus information for the given key.
    pub fn status_for_key(key: Key) -> ImageCacheStatus {
        todo!()
    }
}

// impl<T: Default> Default for ImageProvider<T> {
//     fn default() -> Self {
//         Self(Default::default())
//     }
// }

#[allow(dead_code)]
pub struct ImageStreamCompleter {
    // Whether any listeners are currently registered.
    has_listeners: bool,
}

impl ImageStreamCompleter {
    // Adds a listener callback that is called whenever a new concrete ImageInfo object is available or an error is reported.
    // If a concrete image is already available, or if an error has been already reported,
    // this object will notify the listener synchronously.
    pub fn add_listener(listener: ImageStreamListener) {}

    // Adds a callback to call when removeListener results in an empty list of listeners and there are no keepAlive handles outstanding.
    pub fn add_on_last_listener_removed_callback(callback: Box<dyn Fn()>) {}

    // // Creates an ImageStreamCompleterHandle that will prevent this stream from being disposed at least until the handle is disposed.
    // pub fn keep_alive() -> ImageStreamCompleterHandle {
    //     todo!()
    // }

    // Stops the specified listener from receiving image stream events.
    pub fn remove_listener(listener: ImageStreamListener) {}

    // Removes a callback previously supplied to addOnLastListenerRemovedCallback.
    pub fn remove_on_last_listener_removed_callback(callback: Box<dyn Fn()>) {}

    // // Calls all the registered error listeners to notify them of an error that occurred while resolving the image.
    // pub fn report_error(
    //     context: Option<DiagnosticsNode>,
    //     exception: Object,
    //     stack: Option<StackTrace>,
    //     information_collector: Option<InformationCollector>,
    //     silent: bool, /*= false*/
    // ) {
    // }

    // Calls all the registered ImageChunkListeners (listeners with an ImageStreamListener.onChunk specified) to notify them of a new ImageChunkEvent.
    pub fn report_image_chunk_event(event: ImageChunkEvent) {}

    // Calls all the registered listeners to notify them of a new image.
    pub fn set_image(image: ImageInfo) {}
}

impl Default for ImageStreamCompleter {
    fn default() -> Self {
        Self {
            has_listeners: Default::default(),
        }
    }
}

// Fn(bytes: Uint8List, cache_width: Option<i32>, cache_height: Option<i32>, allow_upscaling: bool) -> impl Future<Codec>
pub type DecoderCallback =
    dyn Fn(&[u8], Option<i32>, Option<i32>, bool) -> Box<dyn Future<Output = Codec>>;

// Fn(exception: Object, stack_trace: Option<StackTrace>)
pub type ImageErrorListener = dyn Fn();

// Key is Generic here
pub trait ImageProvider /*<T>*/ {
    // Called by resolve to create the ImageStream it returns.
    fn create_stream(&self, configuration: ImageConfiguration) -> ImageStream;

    // Evicts an entry from the image cache.
    fn evict(
        &self,
        cache: Option<ImageCache>,
        configuration: ImageConfiguration, /*= ImageConfiguration.empty*/
    ) -> Box<dyn Future<Output = bool>>;

    // Converts a key into an ImageStreamCompleter, and begins fetching the image.
    fn load(&self, key: Key, decode: Box<DecoderCallback>) -> ImageStreamCompleter;

    // Returns the cache location for the key that this ImageProvider creates.
    fn obtain_cache_status(
        &self,
        configuration: ImageConfiguration,
        handle_error: Option<Box<ImageErrorListener>>,
    ) -> Box<dyn Future<Output = Option<ImageCacheStatus>>>;

    // Converts an ImageProvider's settings plus an ImageConfiguration to a key that describes the precise image to load.
    fn obtain_key(&self, configuration: ImageConfiguration) -> Box<dyn Future<Output = Key>>;

    // Resolves this image provider using the given configuration, returning an ImageStream.
    fn resolve(&self, configuration: ImageConfiguration) -> ImageStream;

    // Called by resolve with the key returned by obtainKey.
    fn resolve_stream_for_key(
        &self,
        configuration: ImageConfiguration,
        stream: ImageStream,
        key: Key,
        handle_error: Option<Box<ImageErrorListener>>,
    );
}