% Author: Pascal Bercher <pascal.bercher -~AT~- anu.edu.au>
% Version: 3.0 (2025-03-05)
% 
% Change Log:
% 2.0 -> 3.0 
% - Added causalLink label macro
% - Removed code duplication
% - Renamed files and folders standardized naming
% - Revised instructions

% Load necessary packages and styles
\RequirePackage{tikz}
\RequirePackage{listofitems}

% Load required TikZ libraries directly
\usetikzlibrary{calc, positioning, decorations.pathreplacing, decorations.markings}

% this allows the definition of causal links, which place dots on the start and end of the link
\tikzset{
  causalLink/.style={
    ->,
    shorten <= 0.15cm,
    shorten >= 0.15cm,
    postaction={
      decorate,
      decoration={
        markings,
        % Not using exaxtly 0 and 1 is a hack sugested by chatGPT 
        % because otherwise for long links the goal dots are not placed
        mark=at position 0.0001 with {\fill circle[radius=1pt];},
        mark=at position 0.9999 with {\fill circle[radius=1pt];}
      }
    }
  }
}

% Name of Action/.style n args={number of objects}{
%    {action= 
%    % number of precs/effs
%    {num of precondition lines (on the left side of action)}
%    {num of effect lines (on the right side of action)}
%    % prec/eff labels
%    {sequence of precondition labels}
%    {sequence of effect labels}
%    % length of precs/effs
%    {length of preconditions}
%    {length of effects}
%    % action name
%    {action name}
%    % prec/eff label position
%    {precondition/effect label position: side or top}
%    {height of node}
%  }

\tikzset{
    action/.style n args={9}{
        draw,
        rounded corners,
        minimum width=3cm,
        fill=cyan,
        minimum height={#9},
        label={center:#7},
        append after command={
            \pgfextra{
                % Define the node name
                \edef\nodename{\tikzlastnode}
                \ifx#3\empty % Check if label list is empty
                \else % Process only if not empty
                    % Read the label content
                    \setsepchar{,}
                    \readlist\nameparts{\nodename}
                    \setsepchar{,}
                    
                    \ifnum#8=0\relax
                    % Define positions for preconditions and effects relative to the node with shifts
                        \ifnum#1>0
                        \readlist\labellist{#3}
                        \foreach \i in {1,...,#1} {
                            % Precondition coordinates and lines
                            \coordinate (\nodename-pre-\i) at ([xshift=-#5cm, yshift=#9/2-#9/(#1+1)*(\i)] \nodename.west);
                            \draw (\nodename.west |- \nodename-pre-\i) -- +(-#5,0) node [midway, above, sloped, font=\scriptsize] {\labellist[\i]};
                        }
                        \fi;
                        \readlist\labellist{#4}
                        \ifnum#2>0
                        \foreach \j in {1,...,#2} {
                            % Effect coordinates and lines
                            \coordinate (\nodename-eff-\j) at ([xshift=#6cm, yshift=#9/2-#9/(#2+1)*(\j)] \nodename.east);
                            \draw (\nodename.east |- \nodename-eff-\j) -- +(#6,0) node [midway, above, sloped, font=\scriptsize] {\labellist[\j]};
                        }
                        \fi;
                    \else
                        \ifnum#1>0
                        \readlist\labellist{#3}
                        \foreach \i in {1,...,#1} {
                            % Precondition coordinates and lines
                            \coordinate (\nodename-pre-\i) at ([xshift=-#5cm, yshift=#9/2-#9/(#1+1)*(\i)] \nodename.west);
                            \draw (\nodename.west |- \nodename-pre-\i) -- +(-#5,0) node [xshift=-(#5+0.5cm), sloped, font=\scriptsize]{\labellist[\i]};
                        }
                        \fi;
                        \readlist\labellist{#4}
                        \ifnum#2>0
                        \foreach \j in {1,...,#2} {
                            % Effect coordinates and lines
                            \coordinate (\nodename-eff-\j) at ([xshift=#6 cm, yshift=#9/2-#9/(#2+1)*(\j)] \nodename.east);
                            \draw (\nodename.east |- \nodename-eff-\j) -- +(#6,0) node [xshift=(#5+0.5 cm), font=\scriptsize] {\labellist[\j]};
                        }
                        \fi;
                    \fi;
                \fi;
            }
        },
        label content/.initial={#3}
    }
}

% INIT/.style={
%     init={
%         {number of effects},
%         {effects},
%         {effects length},
%         {height of init}}}

% GOAL/.style={
%   goal={
%     {number of preconditions},
%     {preconditions},
%     {preconditions length},
%     {height of goal}}}

\tikzset{
    base/.style n args={6}{
        draw,
        minimum width=0.05cm,
        fill=black,
        minimum height={#6},
        append after command={
            \pgfextra{
                \edef\nodename{\tikzlastnode}
                \setsepchar{,}
                \readlist\labellist{#2}
                \foreach \i in {1,...,#1} {
                    \coordinate (\nodename-#5-\i) at ([xshift=#3 cm, yshift=#6/2-#6/(#1+1)*(\i)] \nodename.#4);
                    \draw (\nodename.#4 |- \nodename-#5-\i) -- +(#3,0)
                        node [midway, above, sloped, font=\scriptsize] {\labellist[\i]};
                }
            }
        }
    }
}


\tikzset{
    % Init style
    init/.style n args={4}{
        base={#1}{#2}{#3}{east}{eff}{#4}
    }
}

\tikzset{
    % Goal style
    goal/.style n args={4}{
        base={#1}{#2}{-#3}{west}{pre}{#4}
    }
}