## BEGIN_IMPORT
from pywargame.vassal.traits.basic     import *
from pywargame.vassal.traits.sendto    import *
from pywargame.vassal.traits.layer     import *
from pywargame.vassal.traits.place     import *
from pywargame.vassal.traits.click     import *
from pywargame.vassal.traits.nonrect   import *
from pywargame.vassal.traits.stack     import *
from pywargame.vassal.traits.movefixed import *
from pywargame.vassal.traits.moved     import *
from pywargame.vassal.traits.label     import *
from pywargame.vassal.traits.trail     import *
from pywargame.vassal.traits.cargo     import *
from .. common import VerboseGuard
## END_IMPORT



class Scaler:    
    def __init__(self,factor):
        self._factor       = factor
        self._traitScalers = {
            BasicTrait:        self.scaleBasic,
            SendtoTrait:       self.scaleSendto,
            LayerTrait:        self.scaleLayer,
            PlaceTrait:        self.scalePlace,
            ReplaceTrait:      self.scaleReplace,
            ClickTrait:        self.scaleClick,
            NonRectangleTrait: self.scaleNonRect,
            BasicDeck:         self.scaleDeckPiece,
            StackTrait:        self.scaleStack,
            MoveFixedTrait:    self.scaleMoveFixed,
            MovedTrait:        self.scaleMoved,
            LabelTrait:        self.scaleLabel,
            TrailTrait:        self.scaleTrail,
            CargoTrait:        self.scaleCargo,
        }
        self._notDone = set()
        

    def sign(self,val):
        return -1 if val < 0 else 1
    
    def scaleInt(self,val):
        return int(val * self._factor + self.sign(val) * .5)

    def scaleKeyInt(self,cont,key):
        try:
            old       = int(cont[key])
            cont[key] = self.scaleInt(old)
        except:
            pass
        
    def scaleModule(self,build):
        with VerboseGuard(f'Scaling the module') as vg:
            game        = build.getGame()
            self._icons = [k['icon'] for k in game.getGameMassKeys().values()]

            vg(f'Scaling maps')
            maps        = game.getMaps(asdict=False)
            for map in maps:
                self.scaleMap(map)

            vg(f'Scaling pieces')
            pieces      = game.getPieces()
            for piece in pieces:
                self.scalePiece(piece)


    def scaleMap(self,map):
        with VerboseGuard(f'Scaling map {map["mapName"]}') as vg:
            self._icons.append(map['icon'])
            self._icons.append(map['markUnmovedIcon'])

            vg(f'Scaling decks')
            decks  = map.getDecks(False)
            if decks is not None:
                for deck in decks:
                    self.scaleDeck(deck)
            
            vg(f'Scaling at-start')
            atstarts = map.getAtStarts(False)
            if atstarts is not None:
                for atstart in atstarts:
                    self.scaleAtStart(atstart)
            
            vg(f'Scaling boards')
            boards = map.getBoards(asdict=False)
            if boards is not None:
                for board in boards:
                    self.scaleBoard(board)


    def scaleDeck(self,deck):
        with VerboseGuard(f'Scaling deck {deck["name"]} '
                          f'{deck["width"]}x{deck["height"]}') as vg:
            self.scaleKeyInt(deck,'x')
            self.scaleKeyInt(deck,'y')
            self.scaleKeyInt(deck,'width')
            self.scaleKeyInt(deck,'height')

    def scaleAtStart(self,atstart):
        self.scaleKeyInt(atstart,'x')
        self.scaleKeyInt(atstart,'y')

    def scaleBoard(self,board):

        with VerboseGuard(f'Scaling board {board["name"]} '
                          f'{board["width"]}x{board["height"]}') as vg:
            self.scaleKeyInt(board,'width')
            self.scaleKeyInt(board,'height')
            
            zones = board.getZones(asdict=False)
            if zones is None:
                return
    
            for zone in zones:
                self.scaleZone(zone)

    def scaleZone(self,zone):
        with VerboseGuard(f'Scaling zone {zone["name"]}') as vg:
            path         = zone['path']
            coords       = [[int(c) for c in p.split(',')]
                            for p in path.split(';')]
            coords       = [[self.scaleInt(c) for c in p] for p in coords]
            zone['path'] = ';'.join([','.join([f'{c}' for c in p])
                                     for p in coords])
            
            hgrids       = zone.getHexGrids()
            sgrids       = zone.getSquareGrids()
            grids        = ((hgrids if hgrids else []) +
                            (sgrids if sgrids else []))

            vg(f'Scaling {len(grids)} rectangular and hex grids')
            for grid in grids:
                self.scaleGrid(grid)
            
            rgrids = zone.getRegionGrids()
            if not rgrids: return
            
            vg(f'Scaling {len(rgrids)} irregular grids')
            for grid in rgrids:
                self.scaleRegionGrid(grid)


    def scaleGrid(self,grid):
        grid['dx'] = float(grid['dx']) * self._factor
        grid['dy'] = float(grid['dy']) * self._factor
        self.scaleKeyInt(grid, 'x0')
        self.scaleKeyInt(grid, 'y0')

        numberings = grid.getNumbering()
        if numberings is None:
            return

        for numbering in numberings:
            self.scaleKeyInt(numbering, 'fontSize')
            self.scaleKeyInt(numbering, 'hDrawOff')
            self.scaleKeyInt(numbering, 'vDrawOff')
        

    def scaleRegionGrid(self,grid):
        # print(grid.getMap()['mapName']+'/'+
        #       grid.getBoard()['name']+'/'+
        #       grid.getZone()['name'])
        # grid.print()

        regions = grid.getRegions()
        if regions is None:
            return

        for _,region in regions.items():
            self.scaleKeyInt(region,'originx')
            self.scaleKeyInt(region,'originy')


    def scalePiece(self,piece):
        #with VerboseGuard(f'Scaling piece {piece["entryName"]}') as vg:
        self.scaleKeyInt(piece,'height')
        self.scaleKeyInt(piece,'width')

        traits          = piece.getTraits()
        self.scaleTraits(traits)

        piece.setTraits(*traits)


    def scaleTraits(self,traits):
        for trait in traits:
            scaler = self._traitScalers.get(trait.__class__, self.scaleTrait)
            scaler(trait)

    def scaleTrait(self,trait):
        # print(f'No scaling for {trait}')
        # pass
        self._notDone.add(trait.__class__.__name__)
    
    def scaleBasic(self,trait):
        # print(f'Scaling basic trait {trait}')
        # trait.print()

        self.scaleKeyInt(trait,'x')
        self.scaleKeyInt(trait,'y')
        props      = trait.getProperties()
        for k in ['OldX','OldY','ClickedX','ClickedY',
                  'OldMatOffsetX', 'OldMatOffsetY']:
            if k in props and props[k] != '':
                self.scaleKeyInt(props,k)
    
        trait.setProperties(**props)
        # trait.print()
    
    def scaleSendto(self,trait):
        # trait.print()
        self.scaleKeyInt(trait,'x')
        self.scaleKeyInt(trait,'y')
        self.scaleKeyInt(trait,'xidx')
        self.scaleKeyInt(trait,'yidx')
        # trait.print()
    
    def scaleLayer(self,trait):
        # print(f'Scaling layer trait {trait}')
        self.scaleKeyInt(trait,'underXoff')
        self.scaleKeyInt(trait,'underYoff')
        # trait.print()
    
    def scalePlace(self,trait):
        # print(f'Scaling place trait {trait}')
        self.scaleKeyInt(trait,'xOffset')
        self.scaleKeyInt(trait,'yOffset')
        trait.cleanEmbedded()
        # trait.print()
    
    def scaleReplace(self,trait):
        # print(f'Scaling replace trait {trait}')
        self.scaleKeyInt(trait,'xOffset')
        self.scaleKeyInt(trait,'yOffset')
        trait.cleanEmbedded()
        # trait.print()
    
    def scaleClick(self,trait):
        # print(f'Scaling click trait {trait}')
        # trait.print()
        self.scaleKeyInt(trait,'x')
        self.scaleKeyInt(trait,'y')
        self.scaleKeyInt(trait,'width')
        self.scaleKeyInt(trait,'height')
        # Scale points
        if int(trait['npoints']) > 0:
            trait['points'] = ';'.join([str(self.scaleInt(int(p)))
                                        for p in trait['points'].split(';')])
        # trait.print()
    
    def scaleNonRect(self,trait):
        # print(f'Scaling NonRectangle trait {trait}')
        trait['scale'] = float(trait['scale']) * self._factor
        # trait.print()
        
    def scaleDeckPiece(self,trait):
        # print(f'Scaling deck trait {trait}')
        self.scaleKeyInt(trait,'width')
        self.scaleKeyInt(trait,'height')
        self.scaleKeyInt(trait,'x')
        self.scaleKeyInt(trait,'y')
    
    def scaleStack(self,trait):
        # print(f'Scaling stack trait {trait}')
        self.scaleKeyInt(trait,'x')
        self.scaleKeyInt(trait,'y')
        # trait.print()
    
    def scaleMoveFixed(self,trait):
        # print(f'Scaling moved fixed trait {trait}')
        self.scaleKeyInt(trait,'dx')
        self.scaleKeyInt(trait,'dy')
        self.scaleKeyInt(trait,'xStep')
        self.scaleKeyInt(trait,'yStep')
        
    def scaleMoved(self,trait):
        # print(f'Scaling moved trait {trait}')
        self.scaleKeyInt(trait,'xoff')
        self.scaleKeyInt(trait,'yoff')
        
    def scaleLabel(self,trait):
        # print(f'Scaling label trait {trait}')
        self.scaleKeyInt(trait,'verticalOff')
        self.scaleKeyInt(trait,'horizontalOff')
        
    def scaleTrail(self,trait):
        # print(f'Scaling label trait {trait}')
        self.scaleKeyInt(trait,'lineWidth')

    def scaleCargo(self,trait):
        self.scaleKeyInt(trait,'detectionDistanceX')
        self.scaleKeyInt(trait,'detectionDistancey')

#
# EOF
#

    


    
    
    
        
