--[[----------------------------------------------------------------------------

WFImageOrientation.lua

--------------------------------------------------------------------------------

ADOBE CONFIDENTIAL
------------------
Copyright 2015 Adobe Systems Incorporated
All Rights Reserved.

NOTICE: All information contained herein is, and remains the property of
Adobe Systems Incorporated and its suppliers, if any. The intellectual and
technical concepts contained herein are proprietary to Adobe Systems
Incorporated and its suppliers and are protected by all applicable
intellectual property laws, including trade secret and copyright laws.
Dissemination of this information or reproduction of this material is
strictly forbidden unless prior written permission is obtained from
Adobe Systems Incorporated.

----------------------------------------------------------------------------]]--

local WFImageOrientation = {}

--------------------------------------------------------------------------------

--[[
	TIFF Orientations:
		1 = Horizontal (normal) 
		2 = Mirror horizontal 
		3 = Rotate 180 
		4 = Mirror vertical 
		5 = Mirror horizontal and rotate 270 CW 
		6 = Rotate 90 CW 
		7 = Mirror horizontal and rotate 90 CW 
		8 = Rotate 270 CW
]]--

local swapDimensions = {
	false, 	-- 1 (AB)
	false,	-- 2 (BA)
	false,	-- 3 (CD)
	false,	-- 4 (DC)
	true,	-- 5 (CB)
	true,	-- 6 (BC)
	true,	-- 7 (AD)
	true,	-- 8 (DA)	
}

--------------------------------------------------------------------------------

function WFImageOrientation.swapDimensions( tiffOrientation ) 
	
	return swapDimensions[ tiffOrientation ]

end

--------------------------------------------------------------------------------

local kTiffOrientationToAgOrientationTable = {
	"AB",
	"BA",
	"CD",
	"DC",
	"CB",
	"BC",
	"AD",
	"DA",
}

local kAgOrientationTOTiffOrientationTable = {
	[ "AB" ] = 1,
	[ "BA" ] = 2,
	[ "CD" ] = 3,
	[ "DC" ] = 4,
	[ "CB" ] = 5,
	[ "BC" ] = 6,
	[ "AD" ] = 7,
	[ "DA" ] = 8,
}

local flipHorizontal = {
	AB = "BA",
	BC = "CB",
	CD = "DC",
	DA = "AD",
	AD = "DA",
	DC = "CD",
	CB = "BC",
	BA = "AB",
};

-------------------------------------------------------------------------------

--[[     DC   AD   BA   CB   BC   AB   DA   CD
	    oAB  oBC  oCD  oDA  oAD  oDC  oCB  oBA ]]--
	
local flipVertical = {
	AB = "DC",
	BC = "AD",
	CD = "BA",
	DA = "CB",
	AD = "BC",
	DC = "AB",
	CB = "DA",
	BA = "CD",
};

-------------------------------------------------------------------------------

-- Flip diagonal flips along the diagonal from lower-left to upper-right.

--[[     DC   AD   BA   CB   BC   AB   DA   CD
	    oAB  oBC  oCD  oDA  oAD  oDC  oCB  oBA ]]--
	
local flipDiagonal = {
	AB = "AD",
	BC = "BA",
	CD = "CB",
	DA = "DC",
	AD = "AB",
	DC = "DA",
	CB = "CD",
	BA = "BC",
};

--------------------------------------------------------------------------------

function WFImageOrientation.tiffOrientationToAgOrientation( tiffOrientation )
	return kTiffOrientationToAgOrientationTable[ tiffOrientation ]
end

function WFImageOrientation.AgOrientationTOTiffOrientation( tiffOrientation )
	return kAgOrientationTOTiffOrientationTable[ tiffOrientation ]
end

-------------------------------------------------------------------------------

local function orientationFromOrientationAndFlips( orientation, flipH, flipV, flipD )
	-- concatenates the flips onto the given orientation to give a result
	-- orientation ("rotate further").

	orientation = orientation or "AB"

	if flipH then
		orientation = flipHorizontal[ orientation ]
	end
	
	if flipV then
		orientation = flipVertical[ orientation ]
	end
	
	if flipD then
		orientation = flipDiagonal[ orientation ]
	end
	
	return orientation

end

local function rotate90CW( startOrientation )

	--[[ We want to map:
	
		CD    -->   AC
		AB          BD
		
	A horizontal flip gets us:
	
		DC
		BA
		
	with the pointer now referencing B. A diagonal flip finishes
	the task. ]]--

	return orientationFromOrientationAndFlips( startOrientation, true, false, true )

end

-------------------------------------------------------------------------------

local function rotate90CCW( startOrientation )

	-- Counterclockwise wants the other combination relative to clockwise

	return orientationFromOrientationAndFlips( startOrientation, false, true, true )

end

-------------------------------------------------------------------------------

local function rotate180( startOrientation )

	return orientationFromOrientationAndFlips( startOrientation, true, true, false )

end

-------------------------------------------------------------------------------

function WFImageOrientation.rotate( startOrientation, whichRotation )
	
	if whichRotation == "cw" then
		return rotate90CW( startOrientation )
	elseif whichRotation == "ccw" then
		return rotate90CCW( startOrientation )
	elseif whichRotation == "180" then
		return rotate180( startOrientation )
	else
		assert( false, "unknown whichRotation" )
	end

end

--------------------------------------------------------------------------------

function WFImageOrientation.flip( startOrientation, whichFlip )

	if whichFlip == "flipH" then
		return orientationFromOrientationAndFlips( startOrientation, true, false, false )
	elseif whichFlip == "flipV" then
		return orientationFromOrientationAndFlips( startOrientation, false, true, false )
	else
		assert( false, "unknown whichFlip" )
	end

end

-------------------------------------------------------------------------------

local _convertFlipH = {
	AB = false,
	BC = true,
	CD = true,
	DA = false,
	AD = false,
	DC = false,
	CB = true,
	BA = true,
}

local _convertFlipV = {
	AB = false,
	BC = false,
	CD = true,
	DA = true,
	AD = false,
	DC = true,
	CB = true,
	BA = false,
}

local _convertFlipD = {
	AB = false,
	BC = true,
	CD = false,
	DA = true,
	AD = true,
	DC = false,
	CB = true,
	BA = false,
}

-------------------------------------------------------------------------------

local function convertOrientationToFlips( orientation )
	-- Convert the given orientation to 3 booleans indicating whether we
	-- should flip horizontally, vertically, and diagonally (in that order)
	-- when starting with AB and seeking the desired orientation.
	
	return _convertFlipH[ orientation ],
		   _convertFlipV[ orientation ],
		   _convertFlipD[ orientation ]
	
end

local function doSwapDimensions( orientation )

	local _, _, d = convertOrientationToFlips( orientation )
	
	return d

end

function WFImageOrientation.convertWidthAndHeight( orientation, width, height )

	if doSwapDimensions( orientation ) then
		return height, width
	else
		return width, height
	end
	
end

--------------------------------------------------------------------------------

return WFImageOrientation
