% \iffalse
% --------------------------------------------------------------------
%<*hex>
% \fi
% 
% \subsubsection{Board clipping and frame}
%
% \begin{Macro}{\boardframe}
% 
%   Define the bounding box around the board
%   
%   \begin{Syntax}
%     \cs{boardframe}\oarg{margin}\parg{lower=left}\parg{upper-right}\marg{margin}
%   \end{Syntax}
%   
%   where \meta{lower-left} and \meta{upper-right} specifies the lower
%   left and upper right hexes (inclusive) of the board.  
%   
%
%    \begin{macrocode}
\def\boardframe{%
  \@ifnextchar[{\bo@rdframe}{\bo@rdframe[0]}%]
}
%    \end{macrocode}
%
% Below is our new implementation of \cs{boardframe}.  This is split
% into parts. 
%
%
% First, a macro that will define the path around rectangular placed
% hexes.  This takes 4 mandatory arguments: lower left column and row,
% and upper right column and row, in that order.  It also accepts an
% optional argument.  If this is not empty, then it is assumed to be a
% style to apply, and hexes will be drawn using that style.  The style
% will be passed the hex coordinates and can react accordingly.
% 
%    \begin{macrocode}
\def\bo@rdfr@me{
  \@ifnextchar[{\bo@rdfr@me@}{\bo@rdfr@me@[]}%]
}
\def\bo@rdfr@me@u(#1)#2#3#4#5{
  \hex@coords@conv{#1}
  % \hex@dbg{0}{#1 -> `\hex@x',`\hex@y'}
  \pgfmathparse{min(#2,\hex@x)}\xdef#2{\pgfmathresult}
  \pgfmathparse{min(#3,\hex@y)}\xdef#3{\pgfmathresult}
  \pgfmathparse{max(#4,\hex@x)}\xdef#4{\pgfmathresult}
  \pgfmathparse{max(#5,\hex@y)}\xdef#5{\pgfmathresult}
  \hex@dbg{2}{#1 -> ll=`#2',`#3', ur=`#4',`#5'}
}
\def\bo@rdfr@me@[#1]#2#3#4#5{
  % Define rtmp and a ctmp to by directions 
  \pgfmathparse{int(\hex@coords@row@fac)}\edef\rtmp{\pgfmathresult}
  \pgfmathparse{int(\hex@coords@col@fac)}\edef\ctmp{\pgfmathresult}
  % Define vertices for path 
  \def\ctfv{SW}
  \def\ctsv{SE}
  \def\cbfv{NE}
  \def\cbsv{NW}
  \def\rrfv{E}
  \def\rrsv{NE}
  \def\rlfv{W}
  \def\rlsv{SW}
  % Swap around some definitions based on the row direction
  \ifnum\rtmp<0
    \let\max@short\hex@bot@short@col
    \let\min@short\hex@top@short@col
    \let\swp\ctfv\let\ctfv\cbsv\let\cbsv\swp
    \let\swp\ctsv\let\ctsv\cbfv\let\cbfv\swp
    \def\rrsv{SE}
    \def\rlsv{NW}
  \else
    \let\max@short\hex@top@short@col
    \let\min@short\hex@bot@short@col
  \fi
  % Swap around some definitions based on the column direction
  \ifnum\ctmp<0
    \let\swp\ctfv\let\ctfv\ctsv\let\ctsv\swp
    \let\swp\cbfv\let\cbfv\cbsv\let\cbsv\swp
    \let\swp\rrfv\let\rrfv\rlsv\let\rlsv\swp
    \let\swp\rrsv\let\rrsv\rlfv\let\rlfv\swp
  \fi
  % Define tmp = 0 if no shorts, 1 if top short, 2 if both  
  \pgfmathparse{ifthenelse(\hex@got@top@short,
    ifthenelse(\hex@got@bot@short,2,1),0)}\edef\tmp{\pgfmathresult}
  % If top-short, set factors 
  \ifnum\tmp=1
    \def\mnf{-1}
    \def\mxf{-1}
    \def\mnn{}
    \def\mxn{}
  % If both short, set factors 
  \else\ifnum\tmp=2
    \def\mnf{\rtmp}
    \def\mxf{(-\rtmp)}
    % If inverse rows, set factors 
    \ifnum\rtmp<0
      \def\mnn{}
      \def\mxn{not}
    \else
      \def\mnn{not}
      \def\mxn{}
    \fi
  % If none is short
  \else
    \def\mnf{1}
    \def\mxf{1}
    \def\mnn{not}
    \def\mxn{not}
  \fi\fi
  % Define row@mn to give least row of column  
  \def\row@mn##1{%   
    \pgfmathparse{int(#3+\mnf*
      \hex@coords@row@fac*\min@short(##1)*
      \mnn(\min@short(\hex@coords@col@off)))} 
    \edef\lr{\pgfmathresult}}
  % Define row@mx to give largest row of column
  \def\row@mx##1{%
    \pgfmathparse{int(#5+\mxf* 
      \hex@coords@row@fac*\max@short(##1)*
      \mxn(\max@short(\hex@coords@col@off)))}
    \edef\ur{\pgfmathresult}}
  % 
  % 
  % Below defines a path around the perimeter of the hexes.
  %
  \def\@llx{10000}
  \def\@lly{10000}
  \def\@urx{-10000}
  \def\@ury{-10000}
  % Start with an empty path 
  \def\p{}
  % Loop across least row (can be top if \rtmp<0)
  \foreach \c in {#2,...,#4}{%
    \row@mn{\c}
    \row@mx{\c}
    % \message{^^JColumn: `\c' -> `\lr',`\ur' (#3,#5)}
  }
  \foreach \c in {#2,...,#4}{%
    \row@mn{\c}
    \xdef\p{\p
      (hex cs:c=\c,r=\lr,v=\ctfv)--
      (hex cs:c=\c,r=\lr,v=\ctsv)--}
    \bo@rdfr@me@u(c=\c,r=\lr,v=\ctfv)\@llx\@lly\@urx\@ury
    \bo@rdfr@me@u(c=\c,r=\lr,v=\ctsv)\@llx\@lly\@urx\@ury
  }
  % Go up (down if \rtmp<0) right side
  \row@mn{#4}
  \row@mx{#4}
  \foreach \r in {\lr,...,\ur}{%
    \xdef\p{\p
      (hex cs:c=#4,r=\r,v=\rrfv)--
      (hex cs:c=#4,r=\r,v=\rrsv)--}
    \bo@rdfr@me@u(c=#4,r=\r,v=\rrfv)\@llx\@lly\@urx\@ury
    \bo@rdfr@me@u(c=#4,r=\r,v=\rrsv)\@llx\@lly\@urx\@ury
  }
  % Go across largest row (can be bottom if \rtmp<0)
  \foreach \c in {#4,...,#2}{%
    \row@mx{\c}
    % \message{^^JColumn: `\c', max:`\ur'}
    \xdef\p{\p
      (hex cs:c=\c,r=\ur,v=\cbfv)--
      (hex cs:c=\c,r=\ur,v=\cbsv)--}
    \bo@rdfr@me@u(c=\c,r=\ur,v=\cbfv)\@llx\@lly\@urx\@ury
    \bo@rdfr@me@u(c=\c,r=\ur,v=\cbsv)\@llx\@lly\@urx\@ury
  }
  % Go up (down if \rtmp<0) left side.
  \row@mn{#2}
  \row@mx{#2}
  \foreach \r in {\ur,...,\lr}{%
    \xdef\p{\p
       (hex cs:c=#2,r=\r,v=\rlfv)--
       (hex cs:c=#2,r=\r,v=\rlsv)--}
    \bo@rdfr@me@u(c=#2,r=\r,v=\rlfv)\@llx\@lly\@urx\@ury
    \bo@rdfr@me@u(c=#2,r=\r,v=\rlsv)\@llx\@lly\@urx\@ury
  }
  % End path with cycle  
  \edef\p{\p cycle}
  % Define global path 
  \global\let\hex@board@path\p
  \hex@dbg{3}{Hex board path: `\meaning\hex@board@path'}
  % If an optional argument was given, then use that to actually make
  % hexes. 
  \ifx|#1|\else
    \foreach[count=\nc] \c in {#2,...,#4}{%
      \row@mn{\c}
      \row@mx{\c}
      \foreach \r in {\lr,...,\ur}{%
        \hex[#1={\c,\r}](c=\c,r=\r)
      }
    }
  \fi  
}
%    \end{macrocode}
%
%
% This is a no operations style used as default for the macro
% \cs{boardhexes} below.
% 
%    \begin{macrocode}
\tikzset{%
  /hex/board/no op/.style args={#1,#2}{}}
%    \end{macrocode}
%
% This macro will make the actual hexes using the specified, optional,
% style.  It builds on \cs{bo@rdfr@me} above.
% 
%    \begin{macrocode}
\def\boardhexes{%
  \@ifnextchar[{\bo@rdhexes}{\bo@rdhexes[board/no op]}%]
}
\def\bo@rdhexes[#1](#2)(#3){%
  \hex@coords@conv{#2}
  \edef\llc{\hex@col}
  \edef\llr{\hex@row}
  \hex@coords@conv{#3}
  \edef\urc{\hex@col}
  \edef\urr{\hex@row}
  \bo@rdfr@me[#1]{\llc}{\llr}{\urc}{\urr}}
%    \end{macrocode}
%
% Creates a board frame using \cs{bo@rdfr@me}. 
% 
%    \begin{macrocode}
\tikzset{board frame bb/.code={
    \pgfkeys{
      %/tikz/local bounding box=tmp board frame,
      /tikz/transform shape,
      /tikz/execute at end scope={%
        % \hex@dbg{1}{Getting board frame BB}
        %\wg@get@bb{tmp board frame}
        \global\let\llx\@llx
        \global\let\lly\@lly
        \global\let\urx\@urx
        \global\let\ury\@ury
        % \hex@dbg{0}{Board bounding box (\llx,\lly)x(\urx,\ury)}
      }}}}
      
\def\bo@rdframe[#1](#2)(#3){%
  \hex@coords@conv{#2}
  \edef\llc{\hex@col}
  \edef\llr{\hex@row}
  %
  \hex@coords@conv{#3}
  \edef\urc{\hex@col}
  \edef\urr{\hex@row}
  %
  \def\margin{#1}
  %
  % This will store the bounding box in tmp node `board frame'
  \bo@rdfr@me{\llc}{\llr}{\urc}{\urr}%
  \begin{scope}[board frame bb]
    \expandafter\path\hex@board@path;
  \end{scope}
  \hex@dbg{1}{Board frame LL: -> `\llx',`\lly'}
  \pgfmathparse{\llx+ifthenelse(\llx<0,-1,1)*\margin}\edef\llx{\pgfmathresult}
  \pgfmathparse{\lly+ifthenelse(\lly<0,-1,1)*\margin}\edef\lly{\pgfmathresult}
  %
  \hex@dbg{1}{Board frame UR: -> `\urx',`\ury'}
  \pgfmathparse{\urx+ifthenelse(\urx<0,-1,1)*\margin}\edef\urx{\pgfmathresult}
  \pgfmathparse{\ury+ifthenelse(\ury<0,-1,1)*\margin}\edef\ury{\pgfmathresult}
  %
  \pgfmathparse{\urx-\llx}\edef\w{\pgfmathresult}
  \pgfmathparse{\ury-\lly}\edef\h{\pgfmathresult}
  %% Print to the log
  \hex@dbg{0}{Board Frame: (\llx,\lly)x(\urx,\ury) (\w x\h) (\llc,\llr)x(\urc,\urr)}
  %% Possibly draw 
  \draw[hex/board frame/.try](\llx,\lly) rectangle(\urx,\ury);
  %% Store macros 
  \xdef\boardXmin{\llx}%
  \xdef\boardYmin{\lly}%
  \xdef\boardXmax{\urx}%
  \xdef\boardYmax{\ury}%
}  
%    \end{macrocode}
% 
% \end{Macro}
%    
% \begin{Macro}{\boardclip}
% 
%   Clip the board to not show incomplete hexes 
% 
% \begin{Syntax}
%   \cs{boardclip}\marg{nx}\marg{ny}\marg{preaction}  
% \end{Syntax}
%    \begin{macrocode}
\def\boardpath(#1)(#2){
  \hex@coords@reset%
  \tikzset{/hex/coords/.cd, #1}
  \edef\llc{\hex@col}
  \edef\llr{\hex@row}
  %%
  \hex@coords@reset%
  \tikzset{/hex/coords/.cd, #2}
  \edef\urc{\hex@col}
  \edef\urr{\hex@row}
  
  % This will store the bounding box in tmp node `board frame'
  \bo@rdfr@me{\llc}{\llr}{\urc}{\urr}%
  %% Use the path to extract the bounding box 
  %\begin{scope}[local bounding box=board frame]
  %  \expandafter\path\hex@board@path;
  %\end{scope}
  \global\let\hexboardpath\hex@board@path
}

%    \end{macrocode}
%    \begin{macrocode}
\def\boardclip(#1)(#2)#3{%
  \boardpath(#1)(#2)
  \draw \ifx|#3|\else[preaction={#3}]\fi%
  [clip] \hexboardpath;
}
  
%    \end{macrocode}
% \end{Macro}
%    
% 
% \begin{Macro}{\debuggrid}
%  
%   Show a debug grid.  This requires \cs{boardframe}.
%
%    \begin{macrocode}
\def\debuggrid{%
  \foreach \i in {0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1} {%
    \pgfmathparse{\i*\boardW+\boardXmin}%
    \edef\debug@x{\pgfmathresult}%
    \draw [very thin,gray](\debug@x,\boardYmin) --
    (\debug@x,\boardYmax) node [below,rotate=90] at
    (\debug@x,\boardYmin) {$\i$}; }%
  \foreach \i in {0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1} {%
    \pgfmathparse{\i*\boardH+\boardYmin}%
    \edef\debug@x{\pgfmathresult}%
    \draw [very thin,gray] (\boardXmin,\debug@x) --
    (\boardXmax,\debug@x) node [left,rotate=90] at
    (\boardXmin,\debug@x) {$\i$}; } }
%    \end{macrocode}
% \end{Macro}
%
% Some dummy styles.  These will be defined by the export class to
% facilitate getting information from the board.
% 
%    \begin{macrocode}
\tikzset{%
  zoned/.style={},
  zone scope/.style={},
  zone path/.style={}
}
%    \end{macrocode}
% \iffalse
%</hex>
% --------------------------------------------------------------------
% \fi
