#-*- coding:utf-8 -*-
import dircache, os, math, sys
from PIL import Image
from psd_tools import PSDImage
from psd_tools import Group
import json

class Rectangle:
		x = 0
		y = 0
		width = 0
		height = 0
		offX = 0
		offY = 0
		origin_width = 0
		origin_height = 0
		arena = 0
		
		def __init__(self):
			self.name = ""
			pass
			
		def clone(self):
			rst = Rectangle()
			rst.name = self.name
			rst.x = self.x
			rst.y = self.y
			rst.width = self.width
			rst.height = self.height
			rst.arena = self.arena
			rst.offX = self.offX
			rst.offY = self.offY
			rst.origin_width = self.origin_width
			rst.origin_height = self.origin_height
			return rst
			
		def to_dict(self):
				rst = {}
				rst['x'] = self.x
				rst['y'] = self.y
				rst['w'] = self.width
				rst['h'] = self.height
				rst['offX'] = self.offX
				rst['offY'] = self.offY
				rst['sourceW'] = self.origin_width
				rst['sourceH'] = self.origin_height
				return rst
			
class FreeRectangleChoiceHeuristic:
		BestShortSideFit = 0 #< -BSSF: Positions the Rectangle against the short side of a free Rectangle into which it fits the best.
		BestLongSideFit = 1 #< -BLSF: Positions the Rectangle against the long side of a free Rectangle into which it fits the best.
		BestAreaFit = 2 #< -BAF: Positions the Rectangle into the smallest free Rectangle into which it fits.
		BottomLeftRule = 3 #< -BL: Does the Tetris placement.
		ContactPointRule = 4 #< -CP: Choosest the placement where the Rectangle touches other Rectangles as much as possible.

			
class MaxRectsBinPack:
		binWidth = 0
		binHeight = 0
		allowRotations = False
		
		usedRectangles = [] #new Vector.<Rectangle>();
		freeRectangles = [] #new Vector.<Rectangle>();
		
		score1 = 0
		score2 = 0
		bestShortSideFit = 0
		bestLongSideFit = 0
		
		def __init__(self, width, height, rotations = True):
				self.init(width, height, rotations)
				
				
		def init(self, width, height, rotations = True):
				if( self.count(width) % 1 != 0 or self.count(height) % 1 != 0):
						print "Must be 2,4,8,16,32,...512,1024,..."
						return
				self.binWidth = width
				self.binHeight = height
				self.allowRotations = rotations
				
				n = Rectangle()
				n.x = 0
				n.y = 0
				n.width = width
				n.height = height
				
				self.usedRectangles = []
				
				self.freeRectangles = []
				self.freeRectangles.append(n)
				
		def count(self, n):
				if( n >= 2 ):
						return self.count(n / 2)
				return n
				 
		def insert(self, rect, method):
				width = rect.width
				height = rect.height
				name = rect.name
				newNode  = Rectangle()
				score1 = 0
				score2 = 0
				if method == FreeRectangleChoiceHeuristic.BestShortSideFit: 
						newNode = self.findPositionForNewNodeBestShortSideFit(width, height)
				elif method == FreeRectangleChoiceHeuristic.BottomLeftRule: 
						newNode = self.findPositionForNewNodeBottomLeft(width, height, score1, score2)
				elif method == FreeRectangleChoiceHeuristic.ContactPointRule: 
						newNode = self.findPositionForNewNodeContactPoint(width, height, score1)
				elif method == FreeRectangleChoiceHeuristic.BestLongSideFit: 
						newNode = self.findPositionForNewNodeBestLongSideFit(width, height, score2, score1)
				elif method == FreeRectangleChoiceHeuristic.BestAreaFit: 
						newNode = self.findPositionForNewNodeBestAreaFit(width, height, score1, score2)
				newNode.name = name
				newNode.offX = rect.offX
				newNode.offY = rect.offY
				newNode.or
igin_width = rect.origin_width
				newNode.origin_height = rect.origin_height
				newNode.arena = rect.arena
				if newNode.height == 0:
						print "not posi for set"
						return newNode
				
				self.placeRectangle(newNode)
				return newNode
				
		def insert2(self, Rectangles, dst, method):
				del dst[:] #dst.length = 0;
				while(len(Rectangles) > 0):
						bestScore1 = sys.maxint #int.MAX_VA
LUE
						bestScore2 = sys.maxint #int.MAX_VALUE
						bestRectangleIndex = -1
						bestNode = Rectangle()
						
						for i in range(len(Rectangles)):
								score1 = 0
								score2 = 0
								newNode = self.scoreRectangle(Rectangles[i].width, Rectangles[i].height, method, score1, score2)
								newNode.name = Rectangles[i].name
								newNode.offX = Rectangles[i].offX
								newNode.offY = Rectangles[i].offY
								newNode.origin_width = Rectangles[i].origin_width
								newNode.origin_height = Rectangles[i].origin_height
								newNode.arena = Rectangles[i].arena
								if score1 < bestScore1 or (score1 == bestScore1 and score2 < bestScore2):
										bestScore1 = score1
										bestScore2 = score2
										bestNode = newNode
										bestRectangleIndex = i
										
						if (bestRectangleIndex == -1):
								return
						
						self.placeRectangle(bestNode)
						del Rectangles[bestRectangleIndex] #Rectangles.splice(bestRectangleIndex,1)
				
		def placeRectangle(self, node):
				numRectanglesToProcess = len(self.freeRectangles)
				i = 0
				while i < numRectanglesToProcess:
						if self.splitFreeNode(self.freeRectangles[i], node):
								del self.freeRectangles[i] #freeRectangles.splice(i,1);
								i = i - 1
								numRectanglesToProcess = numRectanglesToProcess - 1
						i = i + 1
				
				self.pruneFreeList()
				
				self.usedRectangles.append(node)
				
		def scoreRectangle(self, width,  height, method, score1, score2):
				newNode = Rectangle()
				self.score1 = sys.maxint #int.MAX_VALUE;
				self.score2 = sys.maxint #int.MAX_VALUE;
				if method == FreeRectangleChoiceHeuristic.BestShortSideFit: 
						newNode = self.findPositionForNewNodeBestShortSideFit(width, height)
				elif method == FreeRectangleChoiceHeuristic.BottomLeftRule: 
						newNode = self.findPositionForNewNodeBottomLeft(width, height, self.score1, self.score2)
				elif method == FreeRectangleChoiceHeuristic.ContactPointRule: 
						newNode = self.findPositionForNewNodeContactPoint(width, height, self.score1)
						self.score1 = -self.score1;
				elif method == FreeRectangleChoiceHeuristic.BestLongSideFit: 
						newNode = self.findPositionForNewNodeBestLongSideFit(width, height, self.score2, self.score1)
				elif method == FreeRectangleChoiceHeuristic.BestAreaFit: 
						newNode = self.findPositionForNewNodeBestAreaFit(width, height, self.score1, self.score2)
				
				#// Cannot fit the current Rectangle.
				if newNode.height == 0:
						self.score1 = sys.maxint #int.MAX_VALUE;
						self.score2 = sys.maxint #int.MAX_VALUE;
						print "not posi for set"
				
				return newNode
				
		#Computes the ratio of used surface area.
		def occupancy(self):
				usedSurfaceArea = 0
				for rect in self.usedRectangles:
						usedSurfaceArea = usedSurfaceArea + rect.width * rect.height;
				
				return usedSurfaceArea / (self.binWidth * self.binHeight)
						
		def findPositionForNewNodeBottomLeft(self, width, height, bestY, bestX):
				bestNode = Rectangle()
				
				bestY = sys.maxint;
				topSideY = 0
				for rect in self.freeRectangles:#(var i:int = 0; i < freeRectangles.length; i++) {
						if rect.width >= width and rect.height >= height:
								topSideY = rect.y + height
								if topSideY < bestY or (topSideY == bestY and rect.x < bestX):
										bestNode.x = rect.x
										bestNode.y = rect.y
										bestNode.width = width
										bestNode.height = height
										bestY = topSideY
										bestX = rect.x
						if self.allowRotations or rect.width >= height and rect.height >= width:
								topSideY = rect.y + width
								if topSideY < bestY or (topSideY == bestY and rect.x < bestX):
										bestNode.x = rect.x
										bestNode.y = rect.y
										bestNode.width = height
										bestNode.height = width
										bestY = topSideY
										bestX = rect.x
				return bestNode
						
		def findPositionForNewNodeBestShortSideFit(self, width, height):
				bestNode = Rectangle()
				
				self.bestShortSideFit = sys.maxint #int.MAX_VALUE;
				self.bestLongSideFit = self.score2
				leftoverHoriz = 0
				leftoverVert = 0
				shortSideFit = 0
				longSideFit = 0
				
				for rect in self.freeRectangles: #(var i:int = 0; i < freeRectangles.length; i++) {
						if rect.width >= width and rect.height >= height:
								leftoverHoriz = math.fabs(rect.