// 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 : base.u8,

	seen_frame               : base.bool,
	seen_frame_config        : base.bool,
	frame_config_io_position : base.u64,

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

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
	}

	// 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 > 0xFFFFFFFF {
				return "#bad header"
			}
			x32 = x64 as base.u32
		}

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

	this.frame_config_io_position = args.src.position()

	if args.dst <> nullptr {
		// TODO: a Wuffs (not just C) name for the
		// WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY magic pixfmt constant.
		args.dst.set!(
			pixfmt: 0x47040008,
			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 = 1
}

pub func decoder.decode_frame_config?(dst: nptr base.frame_config, src: base.io_reader) {
	if this.call_sequence < 1 {
		this.decode_image_config?(dst: nullptr, src: args.src)
	} else if this.call_sequence == 1 {
		// No-op.
	} else if this.call_sequence == 2 {
		// TODO: skip frame.
		return base."@end of data"
	} else {
		return base."@end of data"
	}

	if args.dst <> nullptr {
		args.dst.update!(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: 0xFF000000)
	}

	this.seen_frame_config = true
	this.call_sequence = 2
}

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_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 < 2 {
		this.decode_frame_config?(dst: nullptr, src: args.src)
	} else if this.call_sequence == 2 {
		// No-op.
	} else {
		return base."@end of data"
	}

	// TODO: a Wuffs (not just C) name for the
	// WUFFS_BASE__PIXEL_FORMAT__Y magic pixfmt constant.
	status = this.swizzler.prepare!(
		dst_pixfmt: args.dst.pixel_format(),
		dst_palette: args.dst.palette(),
		src_pixfmt: this.util.make_pixel_format(repr: 0x10000008),
		src_palette: this.util.empty_slice_u8(),
		blend: args.blend)
	if not status.is_ok() {
		return status
	}

	// 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 < 0xFFFFFFFF 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 < 0xFFFFFFFF,
			{
				assert dst_x < 0xFFFFFFFF via "a < b: a < c; c <= b"(c: this.width)

				if (dst_x & 7) == 0 {
					c = args.src.read_u8?()
				}
				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!(
					dst: dst, dst_palette: this.util.empty_slice_u8(), src: src[..])

				if dst.length() >= 4 {
					dst = dst[4 ..]
				}

				dst_x += 1
			}
			dst_y += 1
		}
	}

	this.seen_frame = true
	this.call_sequence = 3
}

pub func decoder.ack_metadata_chunk?(src: base.io_reader) {
	// TODO: this final line shouldn't be necessary, here and in some other
	// std/*/*.wuffs functions.
	return ok
}

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.metadata_chunk_length() base.u64 {
	return 0
}

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

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

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

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

pub func decoder.restart_frame!(index: base.u64, io_position: base.u64) base.status {
	if args.index <> 0 {
		return base."#bad argument"
	}
	this.call_sequence = 1
	this.seen_frame = false
	this.seen_frame_config = false
	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.workbuf_len() base.range_ii_u64 {
	return this.util.make_range_ii_u64(min_incl: 0, max_incl: 0)
}
