% Based on the birthday calendar example by Hakon Malmedal
% http://www.texample.net/tikz/examples/birthday-calendar/
%
% 2014 by Sebastian Hugentobler <shugentobler@nulda.ch>

\NeedsTeXFormat{LaTeX2e}[2011/06/27]
\ProvidesPackage{calpage}[2014/12/10 Calendar Page Package]

\ExecuteOptions{}

\ProcessOptions\relax

\usepackage{graphicx}
\usepackage{tikz}
\usepackage[export]{adjustbox}
\usepackage{xparse}
%%%<
\usepackage{verbatim}
%%%>

\usetikzlibrary{calendar,fit}
\usepackage{expl3}

%% Adapted from http://tex.stackexchange.com/a/10199/4771
\tikzoption{day headings}{\tikzstyle{day heading}=[#1]}
\tikzstyle{day heading}=[]
\tikzstyle{day letter headings}=[
    execute before day scope={ \ifdate{day of month=1}{
      \pgfmathsetlength{\pgf@ya}{\tikz@lib@cal@yshift}
      \pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}
      \pgftransformyshift{-\pgf@ya}
      \foreach \d/\l in {0/Montag,1/Dienstag,2/Mittwoch,3/Donnerstag,
                         4/Freitag,5/Samstag,6/Sonntag} {
        \pgf@xa=\d\pgf@xa
        \pgftransformxshift{\pgf@xa-\cellwidth/2}
        \pgftransformyshift{\pgf@ya}
        \node[above=-0.5ex,day heading]{\l};
      }
    }{}
  }
]
%% End

%% Adapted from pgf source
\tikzstyle{month label above centered}=[
  execute before day scope={
    \ifdate{day of month=1}{
      {
        \pgfmathsetlength{\pgf@xa}{\tikz@lib@cal@xshift}
        \pgf@xb=\tikz@lib@cal@width\pgf@xa
        \advance\pgf@xb by-\pgf@xa
        \pgf@xb=.5\pgf@xb
        \pgftransformxshift{\pgf@xb}
        \pgftransformxshift{-\cellwidth/2}
        \pgfmathsetlength{\pgf@y}{\tikz@lib@cal@yshift}
        \pgftransformyshift{0.333\pgf@y}
        \tikzmonthcode
      }
    }{}},
  every month/.append style={anchor=base}
]

\tikzstyle{month label below centered}=[
  execute before day scope={
    \ifdate{day of month=1}{
      {
        \pgfmathsetlength{\pgf@xa}{\tikz@lib@cal@xshift}
        \pgf@xb=\tikz@lib@cal@width\pgf@xa
        \advance\pgf@xb by-\pgf@xa
        \pgf@xb=.48\pgf@xb
        \pgftransformxshift{\pgf@xb}
        \pgftransformxshift{-\cellwidth/2}
        \pgfmathsetlength{\pgf@y}{\tikz@lib@cal@yshift}
        \pgftransformyshift{-19.2em}
        \huge\tikzmonthcode
      }
    }{}},
  every month/.append style={anchor=base}
]
%% End

\ExplSyntaxOn

%% Adapted from http://tex.stackexchange.com/a/56214/4771
%%
% first of all we define the user level commands
\NewDocumentCommand{\addtext}{ m }{ \bdaycal_input_add:n { #1 } }
\NewDocumentCommand{\addtextyear}{ mm }{ \bdaycal_input_add_y:nn { #1 } { #2 } }
\NewDocumentCommand{\showtext}{ }{ \bdaycal_output_direct: }

% allocate variable:
% a sequence for global storage of the inputs;
\seq_new:N \g_bdaycal_input_seq

% store globally an input in the sequence
\cs_new:Npn \bdaycal_input_add:n #1
 {
  \seq_gput_right:Nn \g_bdaycal_input_seq { #1 }
 }

\cs_new:Npn \bdaycal_input_add_y:nn #1 #2
 {
  \seq_gput_right:Nn \g_bdaycal_input_seq { #1 ~ ( \int_to_arabic:n
    { \pgfcalendarifdateyear - #2 } ) }
 }

% how to output in direct order; we simply do a mapping function calling
% \bdaycal_print:n after incrementing the counter
\cs_new_protected:Npn \bdaycal_output_direct:
 {
  \seq_map_inline:Nn \g_bdaycal_input_seq
   {
    \bdaycal_print:n { ##1 }
   }
  \seq_gclear:N \g_bdaycal_input_seq
 }

% the printing macro; change here for adapting to your wishes
\cs_new:Npn \bdaycal_print:n #1
 {
  #1 \par
 }
%% End

%% Knuth's AoCP, vol 1, 2nd ed, pp 155--156
\int_new:N \l_easter_Y_int
\int_new:N \l_easter_G_int
\int_new:N \l_easter_C_int
\int_new:N \l_easter_X_int
\int_new:N \l_easter_Z_int
\int_new:N \l_easter_D_int
\int_new:N \l_easter_E_int
\int_new:N \l_easter_N_int
\int_new:N \l_easter_M_int
\int_new:N \l_easter_julian_day_int

\cs_new:Nn \easter_sunday:n {

  \int_set:Nn \l_easter_Y_int { #1 }

  \int_set:Nn \l_easter_G_int {
    \int_mod:nn { \l_easter_Y_int } { 19 } + 1
  }

  \int_set:Nn \l_easter_C_int {
    \int_div_truncate:nn { \l_easter_Y_int } { 100 } + 1
  }

  \int_set:Nn \l_easter_X_int {
    \int_div_truncate:nn { 3 * \l_easter_C_int } { 4 } - 12
  }

  \int_set:Nn \l_easter_Z_int {
    \int_div_truncate:nn { 8 * \l_easter_C_int + 5 } { 25 } - 5
  }

  \int_set:Nn \l_easter_D_int {
    \int_div_truncate:nn { 5 * \l_easter_Y_int } { 4 } - \l_easter_X_int - 10
  }

  \int_set:Nn \l_easter_E_int {
    \int_mod:nn { 11 * \l_easter_G_int + 20 + \l_easter_Z_int
      - \l_easter_X_int } { 30 }
  }

  % \int_mod:nn behaves strangely.
  \int_compare:nNnT { \l_easter_E_int } < { 0 }
  {
    \int_add:Nn \l_easter_E_int { 30 }
  }

  \int_compare:nNnTF { \l_easter_E_int } = { 25 }
  { % true
    \int_compare:nNnT { \l_easter_G_int } > { 11 }
    { % true
      \int_incr:N \l_easter_E_int
    }
  }
  { % false
    \int_compare:nNnT { \l_easter_E_int } = { 24 }
    { % true
      \int_incr:N \l_easter_E_int
    }
  }

  \int_set:Nn \l_easter_N_int { 44 - \l_easter_E_int }

  \int_compare:nNnT { \l_easter_N_int } < { 21 }
  { % true
    \int_add:Nn \l_easter_N_int { 30 }
  }

  \int_add:Nn \l_easter_N_int {
    7 - \int_mod:nn { \l_easter_D_int + \l_easter_N_int } { 7 }
  }

  \int_compare:nNnTF { \l_easter_N_int } > { 31 }
  { % true
    \int_sub:Nn \l_easter_N_int { 31 }
    \int_set:Nn \l_easter_M_int { 4 } % April
  }
  { % false
    \int_set:Nn \l_easter_M_int { 3 } % March
  }

  \pgfcalendardatetojulian { \l_easter_Y_int -
     \l_easter_M_int - \l_easter_N_int
  } { \l_easter_julian_day_int }

}

\pgfkeys{/pgf/calendar/Easter/.default = 0}
\pgfkeys{/pgf/calendar/Easter/.code =
  {
    \easter_sunday:n { \pgfcalendarifdateyear }
    \int_compare:nNnT { \pgfcalendarifdatejulian }
    =  {\l_easter_julian_day_int + #1}
    { \pgfcalendarmatchestrue }
  }
}

\int_new:N \l_advent_Y_int
\int_new:N \l_advent_xmas_julian_day_int
\int_new:N \l_advent_xmas_week_day_int
\int_new:N \l_advent_julian_day_int

\cs_new:Nn \advent_sunday:n {

  \int_set:Nn \l_advent_Y_int { #1 }

  \pgfcalendardatetojulian { \l_advent_Y_int - 12 - 25 } {
    \l_advent_xmas_julian_day_int }

  \pgfcalendarjuliantoweekday { \l_advent_xmas_julian_day_int } {
    \l_advent_xmas_week_day_int }

  \int_set:Nn \l_advent_julian_day_int {
    \l_advent_xmas_julian_day_int - \l_advent_xmas_week_day_int - 22 }

}

\pgfkeys{/pgf/calendar/Advent/.default = 0}
\pgfkeys{/pgf/calendar/Advent/.code =
  {
    \advent_sunday:n { \pgfcalendarifdateyear }
    \int_compare:nNnT { \pgfcalendarifdatejulian }
    =  {\l_advent_julian_day_int + #1}
    { \pgfcalendarmatchestrue }
  }
}

%% http://www.tondering.dk/claus/cal/week.php#calcweekno
\int_new:N \l_week_number_year_int
\int_new:N \l_week_number_month_int
\int_new:N \l_week_number_day_int
\int_new:N \l_week_number_a_int
\int_new:N \l_week_number_b_int
\int_new:N \l_week_number_c_int
\int_new:N \l_week_number_s_int
\int_new:N \l_week_number_e_int
\int_new:N \l_week_number_f_int
\int_new:N \l_week_number_g_int
\int_new:N \l_week_number_d_int
\int_new:N \l_week_number_n_int
\int_new:N \l_week_number_W_int

\cs_new:Nn \week_number:nnn {

  \int_set:Nn \l_week_number_year_int { #1 }
  \int_set:Nn \l_week_number_month_int { #2 }
  \int_set:Nn \l_week_number_day_int { #3 }

  \int_compare:nNnTF { \l_week_number_month_int } < { 3 } % jan or feb
  { % true

    \int_set:Nn \l_week_number_a_int { \l_week_number_year_int - 1 }

    \int_set:Nn \l_week_number_b_int {
      \int_div_truncate:nn { \l_week_number_a_int } { 4 }
      - \int_div_truncate:nn { \l_week_number_a_int } { 100 }
      + \int_div_truncate:nn { \l_week_number_a_int } { 400 }
    }

    \int_set:Nn \l_week_number_c_int {
      \int_div_truncate:nn { \l_week_number_a_int - 1 } { 4 }
      - \int_div_truncate:nn { \l_week_number_a_int - 1 } { 100 }
      + \int_div_truncate:nn { \l_week_number_a_int - 1 } { 400 }
    }

    \int_set:Nn \l_week_number_s_int {
      \l_week_number_b_int - \l_week_number_c_int }

    \int_zero:N \l_week_number_e_int

    \int_set:Nn \l_week_number_f_int { \l_week_number_day_int - 1
      + 31 * ( \l_week_number_month_int - 1 ) }

  } % end true
  { % false

    \int_set_eq:NN \l_week_number_a_int \l_week_number_year_int

    \int_set:Nn \l_week_number_b_int {
      \int_div_truncate:nn { \l_week_number_a_int } { 4 }
      - \int_div_truncate:nn { \l_week_number_a_int } { 100 }
      + \int_div_truncate:nn { \l_week_number_a_int } { 400 }
    }

    \int_set:Nn \l_week_number_c_int {
      \int_div_truncate:nn { \l_week_number_a_int - 1 } { 4 }
      - \int_div_truncate:nn { \l_week_number_a_int - 1 } { 100 }
      + \int_div_truncate:nn { \l_week_number_a_int - 1 } { 400 }
    }

    \int_set:Nn \l_week_number_s_int {
      \l_week_number_b_int - \l_week_number_c_int }

    \int_set:Nn \l_week_number_e_int { \l_week_number_s_int + 1 }

    \int_set:Nn \l_week_number_f_int { \l_week_number_day_int
      + \int_div_truncate:nn {
        153 * ( \l_week_number_month_int - 3 ) + 2 } { 5 }
      + 58 + \l_week_number_s_int }

  } % end false

  \int_set:Nn \l_week_number_g_int {
    \int_mod:nn { \l_week_number_a_int + \l_week_number_b_int } { 7 }  }

  \int_set:Nn \l_week_number_d_int {
    \int_mod:nn { \l_week_number_f_int + \l_week_number_g_int
      - \l_week_number_e_int } { 7 }  }

  \int_set:Nn \l_week_number_n_int {
    \l_week_number_f_int + 3 - \l_week_number_d_int }

  \int_compare:nNnTF { \l_week_number_n_int } < { 0 }
  { %true

    \int_set:Nn \l_week_number_W_int { 53
      - \int_div_truncate:nn { \l_week_number_g_int
        - \l_week_number_s_int } { 5 } }

  } % end true
  { % false

    \int_compare:nNnTF { \l_week_number_n_int } > { 364
      + \l_week_number_s_int }
    { % true

      \int_set:Nn \l_week_number_W_int { 1 }

    } % end true
    { % false

      \int_set:Nn \l_week_number_W_int { \int_div_truncate:nn {
          \l_week_number_n_int } { 7 } + 1 }

    } % end false

  } % end false

}

%\definecolor{red}{rgb}{0.937254901961,0.16862745098,0.176470588235}

\newsavebox{\flagCH}
\savebox{\flagCH}{
\begin{tikzpicture}
  \fill[red] rectangle (20pt,20pt);
  \fill[white,xshift=7.5pt, yshift=3pt] rectangle (5pt,14pt);
  \fill[white,xshift=3pt, yshift=7.5pt] rectangle (14pt,5pt);
\end{tikzpicture}
}

\pgfkeys{/tikz/week~number/.code =
  {
    \week_number:nnn {
      \pgfcalendarifdateyear } {
      \pgfcalendarifdatemonth } {
      \pgfcalendarifdateday }
    \addtext{ Woche ~ \int_to_arabic:n { \l_week_number_W_int } }
  }
}

\ExplSyntaxOff

\pgfkeys{/tikz/flag-flying day/.code =
  {
    \draw (-\cellwidth,0) node [above right,font=\Huge]
    {\resizebox{!}{0.8ex}{\usebox{\flagCH}}};
  }
}

\pgfkeys{/tikz/observance/.code =
  {
    \addtext{#1}
  }
}

\pgfkeys{/tikz/anniversary/.code 2 args=\addtextyear{#1}{#2}}

\pgfkeys{/tikz/day code =
  {
    \node (lower right) at (0,0) [above left,font=\Large] {\tikzdaytext};
    \node (upper left) at (-\cellwidth,\cellheight)
    [below right,align=left,text width=\cellwidth-\pgflinewidth,
    font=\tiny,black] {\showtext};
    \node (lower left) at (-\cellwidth,0) {};
    \node[draw,
          fit=(lower right) (upper left) (lower left),
          inner sep=1mm] {};
  }
}

\pgfkeys{/tikz/inner sep = 0pt}

\pgfkeys{/tikz/day xshift=\cellwidth+2mm+2mm}

\pgfkeys{/tikz/day yshift=\cellheight+2mm+2mm}

\newlength{\cellheight}
\setlength{\cellheight}{14mm}
\newlength{\cellwidth}
\setlength{\cellwidth}{24.75mm}

\ExplSyntaxOn
\keys_define:nn { hungerford/boxgraphics }
{
  width  .dim_set:N = \l_hungerford_box_wd_dim,
  height .dim_set:N = \l_hungerford_box_ht_dim,
}

\NewDocumentCommand{\boxincludegraphics}{ m m }
{
  \group_begin:
  \keys_set:nn { hungerford/boxgraphics } { #1 }
  \hungerford_include_graphics:n { #2 }
  \group_end:
}

\cs_new_protected:Npn \hungerford_include_graphics:n #1
{
  \adjustbox{
    clip,
    trim={
      0~
      \dim_eval:n { \height-\l_hungerford_box_ht_dim }~
      \dim_eval:n { \width-\l_hungerford_box_wd_dim }~
      0
    }
  }
  {
    \centerline{
      \includegraphics[
        min~width=\l_hungerford_box_wd_dim,
        height=\l_hungerford_box_ht_dim
      ]{#1}
    }
  }
}

\ExplSyntaxOff

\newcommand{\calpage}[3]{
  \offinterlineskip
  \centering
  \vbox{
    \begin{minipage}[t][0.5\textheight][t]{\textwidth}
      \center
      \boxincludegraphics{width=\textwidth, height=170mm}{#1}
      \vspace{2mm}
    \end{minipage}

    \begin{minipage}[b][0.370\textheight][t]{\textwidth}
      \vspace{5mm}
      \begin{center}
        \begin{tikzpicture}[thick]
          \calendar[dates=#2 to #3,
                    week list,
                    month label below centered,
                    month text=\textsc{\%mt},
                    day headings={font=\footnotesize},
                    day letter headings]
            if (Sunday,
            Easter=39,
            equals=01-01,
            equals=08-01,
            equals=12-25) [red]
            if (equals=08-01) [observance=Nationalfeiertag]
            if (Easter) [observance=Ostern]
            if (Easter=39) [observance=Auffahrt]
            if (equals=01-01) [observance=Neujahrstag]
            if (equals=02-23) [observance=Basler Fasnacht]
            if (equals=02-24) [observance=Basler Fasnacht]
            if (equals=02-25) [observance=Basler Fasnacht]
            if (Advent) [observance=Advent]
            if (equals=12-25) [observance=Weihnachten]
            ;
        \end{tikzpicture}
      \end{center}
    \end{minipage}
  }
}

\endinput
