% Copyright 2018-2024 by Romano Giannetti
% Copyright 2015-2024 by Stefan Lindner
% Copyright 2013-2024 by Stefan Erhardt
% Copyright 2007-2024 by Massimo Redaelli
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
% See the files gpl-3.0_license.txt and lppl-1-3c_license.txt for more details.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Bipole label positioning

%% bipole labels and annotation extra style

\ctikzset{bipole label style/.style={}}
\tikzset{bipole label style/.code={
        \ctikzset{bipole label style/.style={#1}}
}}
\tikzset{bipole label append style/.code={
        \ctikzset{bipole label style/.append style={#1}}
}}
\ctikzset{bipole annotation style/.style={}}
\tikzset{bipole annotation style/.code={
        \ctikzset{bipole annotation style/.style={#1}}
}}
\tikzset{bipole annotation append style/.code={
        \ctikzset{bipole annotation style/.append style={#1}}
}}

\ctikzset{label distance/.initial={0pt}}
\ctikzset{annotation distance/.initial={0pt}}

%% Options
\ctikzset{label/.style = { l={#1} } }
\ctikzset{l/.code = {
        \pgfkeys{/tikz/circuitikz/bipole/label/name={#1}}
        \ctikzsetvalof{bipole/label/unit}{}
        \ifpgf@circ@siunitx
            \pgf@circ@handleSI{#1}
            \ifpgf@circ@siunitx@res
                \edef\pgf@temp{\pgf@circ@handleSI@val}
                \pgfkeyslet{/tikz/circuitikz/bipole/label/name}{\pgf@temp}
                \edef\pgf@temp{\pgf@circ@handleSI@unit}
                \pgfkeyslet{/tikz/circuitikz/bipole/label/unit}{\pgf@temp}
            \else
        \fi
        \else
    \fi
}}

\ctikzset{label above/.code = {
        l={#1},
    \circuitikzbasekey/bipole/label/position=90 }
}

\ctikzset{l^/.style = {
        l={#1},
    \circuitikzbasekey/bipole/label/position=90 }
}

\ctikzset{label below/.code = {
        l={#1},
    \circuitikzbasekey/bipole/label/position=-90 }
}

\ctikzset{l_/.style = {
        l={#1},
    \circuitikzbasekey/bipole/label/position=-90 }
}

\ctikzset{annotation/.style = { a={#1} } }
\ctikzset{a/.code = {
    \pgfkeys{/tikz/circuitikz/bipole/annotation/name={#1}}
    \ctikzsetvalof{bipole/annotation/unit}{}
    \ifpgf@circ@siunitx
        \pgf@circ@handleSI{#1}
        \ifpgf@circ@siunitx@res
            \edef\pgf@temp{\pgf@circ@handleSI@val}
            \pgfkeyslet{/tikz/circuitikz/bipole/annotation/name}{\pgf@temp}
            \edef\pgf@temp{\pgf@circ@handleSI@unit}
            \pgfkeyslet{/tikz/circuitikz/bipole/annotation/unit}{\pgf@temp}
        \else
        \fi
    \else
    \fi
}}

\ctikzset{annotation above/.code = {
        a={#1},
    \circuitikzbasekey/bipole/annotation/position=90 }
}

\ctikzset{a^/.style = {
        a={#1},
    \circuitikzbasekey/bipole/annotation/position=90 }
}

\ctikzset{annotation below/.code = {
        a={#1},
    \circuitikzbasekey/bipole/annotation/position=-90 }
}
\ctikzset{a_/.style = {
        a={#1},
    \circuitikzbasekey/bipole/annotation/position=-90 }
}

% This is to adjust spacing for the labels so that they are not cramped on components
\def\pgf@circ@ls{.75ex} % labelspace to have just one point to change

\def\pgf@circ@drawlabels#1{
    \pgfextra{
        % This function will be called with argument #1 equal
        % to "label" or "annotation" form pgfcircpath.tex.
        % pgf@circ@direction is the direction of the path,
        % its value is set in pgfcircpath.tex
        \pgfmathsubtract{\pgf@circ@direction}{90}
        \pgfmathround{\pgfmathresult} % avoid precision loss errors
        \edef\pgf@circ@labanc{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil}

        \edef\pgf@circ@temp{\ctikzvalof{bipole/#1/position}}
        \ifnum \pgf@circ@temp < 0
                \pgfmathadd{\pgf@circ@labanc}{180}
                \edef\pgf@circ@labanc{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil}
        \fi
        % \typeout{INI: TEMP\space\pgf@circ@temp\space LABANC\space\pgf@circ@labanc}
        %
        % normalize the angle values
        %
        \pgfmathmod{\pgf@circ@labanc}{360}
        \edef\pgf@circ@labanc{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil}
        %
        \ifpgf@circuit@bipole@inverted
                \pgfmathadd{\pgf@circ@temp}{180} %If shape is inverted, use opposite anchor
                \edef\pgf@circ@temp{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil}
        \fi
        %
        \ifnum \ctikzvalof{mirror value} = -1
                \pgfmathadd{\pgf@circ@temp}{180} %If shape is mirrored, use opposite anchor
                \edef\pgf@circ@temp{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil}
        \fi
        % \typeout{FIN: TEMP\space\pgf@circ@temp\space LABANC\space\pgf@circ@labanc}
    }
    %Firstly, place a coordinate directly at the edge of the shape
    (\ctikzvalof{bipole/name}.\pgf@circ@temp) coordinate (pgfcirc@labelcoor)
    %now decide, which labels should be drawn
    \pgfextra{
            \edef\pgf@temp{\ctikzvalof{label/align}}
            \def\pgf@circ@temp{straight}
    }
    \ifx\pgf@temp\pgf@circ@temp %straight
            \pgf@circ@drawreglabels{#1}
    \else
            \pgfextra{\def\pgf@circ@temp{rotate}}
            \ifx\pgf@temp\pgf@circ@temp %rotate
                    \pgf@circ@drawrotlabels{#1}
            \else% smart
                    \pgf@circ@drawsmartlabels{#1}
            \fi
    \fi
}


\def\pgf@circ@drawsmartlabels#1{
    \pgfextra{
        \pgfmathmod{\pgf@circ@direction}{90}
        \edef\pgfcircmathresult{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil}
    }
    \ifnum \pgfcircmathresult > 20
    \ifnum \pgfcircmathresult < 70
        \pgf@circ@drawrotlabels{#1}
    \else
        \pgf@circ@drawreglabels{#1}
    \fi
    \else
        \pgf@circ@drawreglabels{#1}
    \fi
    }


\def\pgf@circ@drawrotlabels#1{
    \pgfextra{
        % scale the distances in function of zoom, so that they are not
        % dependent on it but on font size. Thanks to @marmot
        % https://tex.stackexchange.com/a/476018/38080
        % the coefficient is adjusted so that the distance is more or less
        % the same for rotated labels and straight ones (although it will
        % depend on the font, so it's not exact).
        \pgfgettransformentries{\tmpa}{\tmpb}{\tmpc}{\tmpd}{\tmp}{\tmp}%
        \pgfmathsetmacro{\myscale}{sqrt(abs(\tmpa*\tmpd-\tmpb*\tmpc))}% abs should not be needed
        % \typeout{ROT\tmpa\space\tmpb\space\tmpc\space\tmpd\space\myscale}
        \pgfmathsetlength\pgf@circ@res@temp{1.5*\pgf@circ@ls/\myscale+\ctikzvalof{#1 distance}/\myscale}
        \ifnum \ctikzvalof{bipole/#1/position}>0
        %we need some more space for placement below, due to mid-anchor
            \else % we do not have <= in \ifnum...
                \pgf@circ@res@temp=1.5\pgf@circ@res@temp
        \fi
        %Calculate rotation of the label from direction and strip decimals
        \pgfmathsetmacro{\pgfcirclabrot}{round(\pgf@circ@direction)}
        \edef\pgfcirclabrot{\expandafter\pgf@circ@stripdecimals\pgfcirclabrot\pgf@nil}
        % rotate the label at second or third quadrant:
        \ifnum \pgfcirclabrot > 90 \ifnum \pgfcirclabrot < 270
                \pgfmathsubtract{\pgf@circ@direction}{180}
                \edef\pgfcirclabrot{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil}
                %invert the space relationships due to rotated strings
                \ifnum \ctikzvalof{bipole/#1/position}>0
                        \pgf@circ@res@temp=1.5\pgf@circ@res@temp
                \fi
        \fi\fi
        \pgfmathparse{\ctikzvalof{bipole/#1/position}>0?\pgf@circ@direction+90:\pgf@circ@direction-90}%
        \edef\pgf@circ@labposangle{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil}%
        \expandafter\xdef\csname pgfcirc@\pgfcirc@a@prefix#1-direction\endcsname{\pgfcirclabrot}%
        \expandafter\xdef\csname pgfcirc@\pgfcirc@a@prefix-#1-anchor\endcsname{mid}%
    }
    % reset cm is not working correctly here
    % relative ++ movement disrupt to[] +()
    ($(pgfcirc@labelcoor)+(\pgf@circ@labposangle:\the\pgf@circ@res@temp)$) coordinate(pgfcirc@labelcoor)
    node[anchor=mid, rotate=\pgfcirclabrot, \circuitikzbasekey/bipole #1 style]
    (\ctikzvalof{bipole/name}#1){\pgf@circ@finallabels{#1}}
}

\def\pgf@circ@drawreglabels#1{
    %Now calculate all shape positions
    %Use mid-anchor at x-axis and base-anchor at y-axis, respectively.
    %All points between will be addressed by angled-anchors:
    \pgfextra{
        % scale ex-distance to make it independent on scale
        % thanks @marmot see https://tex.stackexchange.com/a/476018/38080
        \pgfgettransformentries{\tmpa}{\tmpb}{\tmpc}{\tmpd}{\tmp}{\tmp}%
        \pgfmathsetmacro{\myscale}{sqrt(abs(\tmpa*\tmpd-\tmpb*\tmpc))}% abs should not be needed
        % \typeout{ROT\tmpa\space\tmpb\space\tmpc\space\tmpd\space\myscale}
        \pgfmathsetlength\pgf@circ@res@temp{\pgf@circ@ls/\myscale+\ctikzvalof{#1 distance}/\myscale}
        \pgfmathadd{\pgf@circ@labanc}{90}
        \pgfmathround{\pgfmathresult}
        \def\pgf@circ@labanctext{\pgf@circ@labanc}
        \edef\pgf@circ@temp{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil}
        \pgfmathparse{mod(\pgf@circ@temp,180)>135?mod(\pgf@circ@temp,180)-180:mod(\pgf@circ@temp,180)}
        \edef\pgfcircmathresult{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil}
    }
    %Values around 90 are at both y-axis
    \ifnum \pgfcircmathresult > 84 \ifnum \pgfcircmathresult< 96
        \pgfextra{\edef\pgf@circ@labpos{\expandafter\pgf@circ@stripdecimals\pgf@circ@direction\pgf@nil}}
        \ifnum \pgf@circ@labpos > 180
            \ifnum \ctikzvalof{bipole/#1/position} > 0
                    \pgfextra{\def\pgf@circ@labanctext{mid west}}
            \else
                    \pgfextra{\def\pgf@circ@labanctext{mid east}}
            \fi
        \else
            \ifnum \ctikzvalof{bipole/#1/position} > 0
                    \pgfextra{\def\pgf@circ@labanctext{mid east}}
            \else
                    \pgfextra{\def\pgf@circ@labanctext{mid west}}
            \fi
        \fi
    \fi\fi
    %Values between -5 and 5 are at pos /neg x-axis
        \ifnum \pgfcircmathresult <6 \ifnum \pgfcircmathresult > -6
            \ifnum \ctikzvalof{bipole/#1/position} < 0
                \ifnum \pgf@circ@labanc > 90
                    % using base coordinate instead of south to naturally align
                    % symbols with descendants; but this invalidate the effect of
                    % the inner sep, so recover it by shifting the anchor
                    % reset cm is not working sometime, use @marmot solution
                    % see https://tex.stackexchange.com/a/476018/38080
                    %  notice that relative ++ movement disrupt to[] +()
                ($(pgfcirc@labelcoor)+(-\pgf@circ@labanc:\pgf@circ@res@temp)$) coordinate(pgfcirc@labelcoor)
                    \pgfextra{\def\pgf@circ@labanctext{base}}%base
                \else
                    \pgfextra{\def\pgf@circ@labanctext{north}}%north
                \fi
             \else
                \ifnum \pgf@circ@labanc < 90
                    % shift, as above
                ($(pgfcirc@labelcoor)+(-\pgf@circ@labanc:\pgf@circ@res@temp)$) coordinate(pgfcirc@labelcoor)
                    \pgfextra{\def\pgf@circ@labanctext{base}}%base
                \else
                    \ifnum \pgf@circ@labanc > 180
                        % this shouldn't  happen, but somehow it does (270 degree anchors)
                        % shift, as above
                    ($(pgfcirc@labelcoor)+(-\pgf@circ@labanc:\pgf@circ@res@temp)$) coordinate(pgfcirc@labelcoor)
                         \pgfextra{\def\pgf@circ@labanctext{base}}%base
                    \else
                      \pgfextra{\def\pgf@circ@labanctext{north}}%north
                   \fi
                \fi
            \fi
        \fi\fi
    \pgfextra{%
        \expandafter\xdef\csname pgfcirc@\pgfcirc@a@prefix#1-direction\endcsname{0}%
        \expandafter\xdef\csname pgfcirc@\pgfcirc@a@prefix-#1-anchor\endcsname{\pgf@circ@labanctext}%
    }
    (pgfcirc@labelcoor) node[anchor=\pgf@circ@labanctext,
    inner sep=0.5\pgf@circ@res@temp, outer sep=0pt, \circuitikzbasekey/bipole #1 style,
        ](\ctikzvalof{bipole/name}#1){\strut\pgf@circ@finallabels{#1}%
    }
}

\def\pgf@circ@finallabels#1{%
    \edef\pgf@temp{}%
    \edef\pgf@circ@temp{\ctikzvalof{bipole/#1/unit}}%
    \ifx\pgf@temp\pgf@circ@temp%
        \ctikzvalof{bipole/#1/name}%
    \else%
        $\SI{\ctikzvalof{bipole/#1/name}}{\ctikzvalof{bipole/#1/unit}}$%
    \fi%
}


%%%% Stacked labels
%
% stacked labels by Romano Giannetti romano@rgtti.com
% heavily based on Claudo Fiandrinos's https://tex.stackexchange.com/a/65792/38080
% \expandafter trick inspired by Matthew Leingang's https://tex.stackexchange.com/a/12272/38080
%
% labels are in a tabular, globally aligned:
%        vertically with key l2 valign (default c)
%        c: center t: top b: bottom
%        horizontally with key l2 align (default l)
%        l: left c: centered r: right
% you can switch sides using l2_=... and l2^=...
% syntax is l2_ = line1 and line2 (same for l2^)
%
\ctikzset{%
    l2 valign/.store in=\pgfcirc@ltwo@valign, l2 valign=c,
    l2 halign/.store in=\pgfcirc@ltwo@halign, l2 halign=l,
}
\ctikzset{l2base/.code n args={2}{
  \pgfkeys{/tikz/circuitikz/bipole/label/name=%
        \bgroup
        \setlength{\tabcolsep}{2pt}%
        \def\pgfcirc@ltwo@tabu{\tabular[\pgfcirc@ltwo@valign]}%
        \expandafter\pgfcirc@ltwo@tabu\expandafter{\pgfcirc@ltwo@halign}%
        #1\\ #2%
        \endtabular
        \egroup
    }%
}}
\ctikzset{l2/.style args={#1and#2}{
        l2base={#1}{#2},
    \circuitikzbasekey/bipole/label/position=90 }
}
\ctikzset{l2 above/.style args={#1and#2}{
        l2base={#1}{#2},
    \circuitikzbasekey/bipole/label/position=90 }
}
\ctikzset{l2^/.style args={#1and#2}{
        l2base={#1}{#2},
    \circuitikzbasekey/bipole/label/position=90 }
}
\ctikzset{l2 below/.style args={#1and#2}{
        l2base={#1}{#2},
    \circuitikzbasekey/bipole/label/position=-90 }
}
\ctikzset{l2_/.style args={#1and#2}{
        l2base={#1}{#2},
    \circuitikzbasekey/bipole/label/position=-90 }
}
%
% the same for annotations
%
\ctikzset{%
    a2 valign/.store in=\pgfcirc@atwo@valign, a2 valign=c,
    a2 halign/.store in=\pgfcirc@atwo@halign, a2 halign=r,
}
\ctikzset{a2base/.code n args={2}{
  \pgfkeys{/tikz/circuitikz/bipole/annotation/name=%
        \bgroup
        \setlength{\tabcolsep}{2pt}%
        \def\pgfcirc@atwo@tabu{\tabular[\pgfcirc@atwo@valign]}%
        \expandafter\pgfcirc@atwo@tabu\expandafter{\pgfcirc@atwo@halign}%
        #1\\ #2%
        \endtabular
        \egroup
    }%
}}
\ctikzset{a2/.style args={#1and#2}{
        a2base={#1}{#2},
    \circuitikzbasekey/bipole/annotation/position=-90 }
}
\ctikzset{a2 above/.style args={#1and#2}{
        a2base={#1}{#2},
    \circuitikzbasekey/bipole/annotation/position=-90 }
}
\ctikzset{a2^/.style args={#1and#2}{
        a2base={#1}{#2},
    \circuitikzbasekey/bipole/annotation/position=-90 }
}
\ctikzset{a2 below/.style args={#1and#2}{
        a2base={#1}{#2},
    \circuitikzbasekey/bipole/annotation/position=90 }
}
\ctikzset{a2_/.style args={#1and#2}{
        a2base={#1}{#2},
    \circuitikzbasekey/bipole/annotation/position=90 }
}

\endinput
