// 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_u32(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_u32(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)
}
