// Copyright 2020 The Wuffs Authors.
//
// 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
//
//    https://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.

pub status "#bad header"

pub const DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE : base.u64 = 0

pub struct decoder? implements base.image_decoder(
	width  : base.u32,
	height : base.u32,

	// Call sequence states:
	//  - 0x00: initial state.
	//  - 0x03: image config decoded.
	//  - 0x04: frame config decoded.
	//  - 0xFF: end-of-data, usually after (the non-animated) frame decoded.
	//
	// State transitions:
	//
	//  - 0x00 -> 0x03: via DIC
	//  - 0x00 -> 0x04: via DFC with implicit DIC
	//  - 0x00 -> 0xFF: via DF  with implicit DIC and DFC
	//
	//  - 0x03 -> 0x04: via DFC
	//  - 0x03 -> 0xFF: via DF  with implicit DFC
	//
	//  - 0x04 -> 0xFF: via DFC
	//  - 0x04 -> 0xFF: via DF
	//
	//  - ???? -> 0x03: via RF  for ???? > 0x00
	//
	// Where:
	//  - DF  is decode_frame
	//  - DFC is decode_frame_config, implicit means nullptr args.dst
	//  - DIC is decode_image_config, implicit means nullptr args.dst
	//  - RF  is restart_frame
	call_sequence : base.u8,

	frame_config_io_position : base.u64,

	swizzler : base.pixel_swizzler,
	util     : base.utility,
)

pub func decoder.set_quirk_enabled!(quirk: base.u32, enabled: base.bool) {
}

pub func decoder.decode_image_config?(dst: nptr base.image_config, src: base.io_reader) {
	var c   : base.u8
	var i   : base.u32
	var x32 : base.u32
	var x64 : base.u64

	if this.call_sequence <> 0 {
		return base."#bad call sequence"
	}

	// TypeField, FixHeaderField.
	i = 0
	while i < 2 {
		c = args.src.read_u8?()
		if c <> 0 {
			return "#bad header"
		}
		i += 1
	} endwhile

	// Width, height.
	i = 0
	while i < 2 {
		x32 = 0

		while true,
			inv i < 2,
		{
			c = args.src.read_u8?()
			x32 |= (c & 0x7F) as base.u32
			if (c >> 7) == 0 {
				break
			}
			x64 = (x32 as base.u64) << 7
			if x64 > 0xFFFF_FFFF {
				return "#bad header"
			}
			x32 = x64 as base.u32
		} endwhile

		if i == 0 {
			this.width = x32
		} else {
			this.height = x32
		}
		i += 1
	} endwhile

	this.frame_config_io_position = args.src.position()

	if args.dst <> nullptr {
		args.dst.set!(
			pixfmt: base.PIXEL_FORMAT__INDEXED__BGRA_BINARY,
			pixsub: 0,
			width: this.width,
			height: this.height,
			first_frame_io_position: this.frame_config_io_position,
			first_frame_is_opaque: true)
	}

	this.call_sequence = 3
}

pub func decoder.decode_frame_config?(dst: nptr base.frame_config, src: base.io_reader) {
	if this.call_sequence < 3 {
		this.decode_image_config?(dst: nullptr, src: args.src)
	} else if this.call_sequence == 3 {
		if this.frame_config_io_position <> args.src.position() {
			return base."#bad restart"
		}
	} else if this.call_sequence == 4 {
		this.call_sequence = 0xFF
		return base."@end of data"
	} else {
		return base."@end of data"
	}

	if args.dst <> nullptr {
		args.dst.set!(bounds: this.util.make_rect_ie_u32(
			min_incl_x: 0,
			min_incl_y: 0,
			max_excl_x: this.width,
			max_excl_y: this.height),
			duration: 0,
			index: 0,
			io_position: this.frame_config_io_position,
			disposal: 0,
			opaque_within_bounds: true,
			overwrite_instead_of_blend: false,
			background_color: 0xFF00_0000)
	}

	this.call_sequence = 4
}

pub func decoder.decode_frame?(dst: ptr base.pixel_buffer, src: base.io_reader, blend: base.pixel_blend, workbuf: slice base.u8, opts: nptr base.decode_frame_options) {
	var status              : base.status
	var dst_pixfmt          : base.pixel_format
	var dst_bits_per_pixel  : base.u32[..= 256]
	var dst_bytes_per_pixel : base.u64[..= 32]
	var dst_x_in_bytes      : base.u64
	var dst_x               : base.u32
	var dst_y               : base.u32
	var tab                 : table base.u8
	var dst                 : slice base.u8
	var src                 : array[1] base.u8
	var c                   : base.u8

	if this.call_sequence < 4 {
		this.decode_frame_config?(dst: nullptr, src: args.src)
	} else if this.call_sequence == 4 {
		// No-op.
	} else {
		return base."@end of data"
	}

	status = this.swizzler.prepare!(
		dst_pixfmt: args.dst.pixel_format(),
		dst_palette: args.dst.palette(),
		src_pixfmt: this.util.make_pixel_format(repr: base.PIXEL_FORMAT__Y),
		src_palette: this.util.empty_slice_u8(),
		blend: args.blend)
	if not status.is_ok() {
		return status
	}

	// TODO: the dst_pixfmt variable shouldn't be necessary. We should be able
	// to chain the two calls: "args.dst.pixel_format().bits_per_pixel()".
	dst_pixfmt = args.dst.pixel_format()
	dst_bits_per_pixel = dst_pixfmt.bits_per_pixel()
	if (dst_bits_per_pixel & 7) <> 0 {
		return base."#unsupported option"
	}
	dst_bytes_per_pixel = (dst_bits_per_pixel / 8) as base.u64

	// TODO: be more efficient than reading one byte at a time.
	if this.width > 0 {
		tab = args.dst.plane(p: 0)
		while dst_y < this.height {
			assert dst_y < 0xFFFF_FFFF via "a < b: a < c; c <= b"(c: this.height)
			dst = tab.row(y: dst_y)
			dst_x = 0

			while dst_x < this.width,
				inv dst_y < 0xFFFF_FFFF,
			{
				assert dst_x < 0xFFFF_FFFF via "a < b: a < c; c <= b"(c: this.width)

				if (dst_x & 7) == 0 {
					while args.src.length() <= 0,
						inv dst_x < 0xFFFF_FFFF,
						inv dst_y < 0xFFFF_FFFF,
						post args.src.length() > 0,
					{
						yield? base."$short read"
						tab = args.dst.plane(p: 0)
						dst = tab.row(y: dst_y)
						dst_x_in_bytes = (dst_x as base.u64) * dst_bytes_per_pixel
						if dst_x_in_bytes <= dst.length() {
							dst = dst[dst_x_in_bytes ..]
						}
					} endwhile
					c = args.src.peek_u8()
					args.src.skip_u32_fast!(actual: 1, worst_case: 1)
				}
				if (c & 0x80) == 0 {
					src[0] = 0x00
				} else {
					src[0] = 0xFF
				}
				// TODO: this should just be "c ~mod<<= 1", but that generates:
				//
				// error: conversion to ‘uint8_t {aka unsigned char}’ from
				// ‘int’ may alter its value [-Werror=conversion]
				//     v_c <<= 1;
				c = (((c as base.u32) << 1) & 0xFF) as base.u8

				this.swizzler.swizzle_interleaved_from_slice!(
					dst: dst, dst_palette: this.util.empty_slice_u8(), src: src[..])

				if dst_bytes_per_pixel <= dst.length() {
					dst = dst[dst_bytes_per_pixel ..]
				}

				dst_x += 1
			} endwhile
			dst_y += 1
		} endwhile
	}

	this.call_sequence = 0xFF
}

pub func decoder.frame_dirty_rect() base.rect_ie_u32 {
	return this.util.make_rect_ie_u32(
		min_incl_x: 0,
		min_incl_y: 0,
		max_excl_x: this.width,
		max_excl_y: this.height)
}

pub func decoder.num_animation_loops() base.u32 {
	return 0
}

pub func decoder.num_decoded_frame_configs() base.u64 {
	if this.call_sequence > 3 {
		return 1
	}
	return 0
}

pub func decoder.num_decoded_frames() base.u64 {
	if this.call_sequence > 4 {
		return 1
	}
	return 0
}

pub func decoder.restart_frame!(index: base.u64, io_position: base.u64) base.status {
	if this.call_sequence < 3 {
		return base."#bad call sequence"
	}
	if args.index <> 0 {
		return base."#bad argument"
	}
	this.call_sequence = 3
	this.frame_config_io_position = args.io_position
	return ok
}

pub func decoder.set_report_metadata!(fourcc: base.u32, report: base.bool) {
	// No-op. WBMP doesn't support metadata.
}

pub func decoder.tell_me_more?(dst: base.io_writer, minfo: nptr base.more_information, src: base.io_reader) {
	return base."#no more information"
}

pub func decoder.workbuf_len() base.range_ii_u64 {
	return this.util.make_range_ii_u64(min_incl: 0, max_incl: 0)
}
