#!/usr/bin/python3
# -*- coding: utf8 -*-
#
#Idee einer dynamischen Erstellung der Skytale-Vorlage
#Autor: Philipp Rumm
#Version: 1.4, cc-by-nc-sa
#Letzte Aenderung: 22. Oktober 2017, 17:00 Uhr
	##Aufnahme der Ideen aus dem IaG-Projekt
	##Implementierung der Wicklungsdehnung
	##Weitere Entferung überflüssigen Codes
	##python-math hinzugefügt
#Letzte Änderung 10. Dezember 2017, 17:13 Uhr
	##Rechtschreibfehler in den Kommentaren behoben
#####################################################################
#Benötigte Bibliotheken, pdflatex per subprocess-call
import argparse
import os
import subprocess
import math

#Der Argument-Parser übernimmt die Konsoleneingabe
#Müsste man andersherum denken, falls es in einer .tex-file aufgerufen werden soll
parser = argparse.ArgumentParser()
parser.add_argument('-n', '--nachricht', default  ='Hallo', help = "Die Nachricht, welche verschlüsselt werden soll")
parser.add_argument('-z', '--zentimeter', default = '4', help = "Zentimeteranteil des Holzstabes")
parser.add_argument('-mm','--millimeter', default = '0', help = "Millimeteranteil des Holzstabes")
args = parser.parse_args()

#Ausrechnen und Ueberpruefung der Geheimtextlänge
if (int(args.zentimeter) > 0) & (int(args.zentimeter) < 9):
	l = int(len(args.nachricht))*(int(args.zentimeter))
else:
	print("Ungueltige Lange. Die Skytale muss einen Umfang im Intervall [1;8.9]cm haben!")
	exit(0)

#Upcase der eingegebenen Nachricht
tempS = args.nachricht.upper()
args.nachricht = tempS

#An dieser Stelle wird ein String definiert um das LaTeX-Dokument zu setzen
TeXstring = r'''\documentclass[12pt,a4paper]{scrartcl}
%%\usepackage[utf8]{inputenc}
%%\usepackage[ngerman]{babel}
%%\usepackage[T1]{fontenc}
%%\usepackage[dvipsnames]{xcolor}
\usepackage[AB]{spioncamp}
\usepackage{tikz}
\usetikzlibrary{calc,positioning,arrows,chains,shapes.geometric, decorations.pathreplacing,decorations.pathmorphing,shapes, matrix,shapes.symbols} 

\usepackage{ifthen}
\usepackage{fontawesome}
\usepackage{xstring}
\usepackage{amsmath}
\usepackage{randomstring}
\usepackage{calc}
\usepackage{etoolbox}

\setlength{\parindent}{0em}

\title{Skytale}
\subtitle{Transposition}

\setrandomstringlength{1}


\begin{document}
\textbf{Die Nachricht lautet: \textit{%(nachricht)s}} \\
\textbf{Der Umfang des Stabes beträgt: ''' + str(int(args.zentimeter)*10 + int(args.millimeter)) + r'''mm} \\

\textbf{Hinweise zur Benutzung}
\begin{itemize}
	\item Die einzelnen Spalten der Skytale werden vertikal gelesen und ausgeschnitten
	\item Bei längeren Nachrichten werden die Spalten hintereinandergeklebt. Dazu findet sich am Ende jeder Spalte ein grauer Kasten als Überlappung zum Kleben
\end{itemize}
\vspace{1cm}
\textbf{Klebeanleitung}\\

\begin{tikzpicture}
\foreach \k in {1,...,4}{
	\draw node [draw,thick,minimum width=1cm,minimum height=1cm] at ({\k},0) {};
	\draw node [draw,thick,minimum width=1cm,minimum height=1cm] at ({\k+8},0) {};
	}
\draw node [draw,thick,minimum width=1cm,minimum height=1cm,fill=gray] at (5,0) {};
	\draw [->,dotted, very thick] (6,0) -- (8,0);
\draw node [draw,thick,minimum width=1cm,minimum height=1cm,fill=gray] at (13,0) {};
	\draw node at (-1,0) {\textbf{1)}};
	\draw node at (-1,-2) {\textbf{2)}};
\foreach \k in {1,...,8}{
	\draw node [draw,thick,minimum width=1cm,minimum height=1cm] at ({\k},-2) {};
	}
	\draw node [draw,thick,minimum width=1cm,minimum height=1cm,fill=gray] at (9,-2) {};
	\draw node at (12,-2) {\textbf{usw.}};

\end{tikzpicture}

\clearpage
\begin{tikzpicture}
\node[rotate=-90] at (-1,1) {\faScissors};
\draw [->,dotted] (-1,0.5) -- (-1,-1.5);
\node [align=left, text=black, draw=white] at (-1.5,-20) {\small Klebe-\\laschen};
\draw [->,dotted] (-2,-21) -- (1,-21);

\foreach \l in {0,...,13}{
\draw [thick] ({-0.5+\l},0.5) -- ({-0.5+\l},-19.5);

\ifthenelse{\l<13}{\draw node [draw,thick,minimum width=1cm,minimum height=1cm,fill=gray] at ({\l},-20) {};}
}
'''
#####################################################################
#Umfang des Stabs bestehend aus Zentimeter- und Millimeterangabe
umfang = float(args.zentimeter)*10 + float(args.millimeter)
#Länge einer Umwicklung -> länger, wegen Spiralform
umfanggewickelt = math.sqrt(umfang*umfang-100)+100/math.sqrt(umfang*umfang-100)
#Differenz zwischen zwei Umläufen -> wichtig für die Verschiebung der Umfanglinien eines Streifens
verschiebung = math.sqrt(100 - (math.sqrt(umfang*umfang-100)*10/umfang)*(math.sqrt(umfang*umfang-100)*10/umfang))
#Winkel, um den die Buchstaben gedreht werden müssen
rotation =  math.degrees(math.asin(verschiebung/10))

#Anzahl der Zeichen in einer (aufgewickelten) Zeile
linelength = math.ceil((int(len(args.nachricht))/int(args.zentimeter)))
#Anzahl der Zeichen insgesamt -> u.U. mehr, da letzte Zeile mit Leerzeichen aufgefüllt werden muss
#l = linelength*int(args.zentimeter)

#Hier beginnt die neue Schleife. Runde bezeichnet die aktuell zu zeichnende Spalte
#Dehnung sorgt dafür, dass die Buchstaben nicht nach oben oder unten weglaufen
dehnung = 1.0
if int(args.zentimeter) > 3:
	dehnung = (float('1.'+ str(args.zentimeter)))
elif int(args.zentimeter) > 4:
	dehnung = (float('1.'+ str(args.zentimeter)))
elif int(args.zentimeter) > 5:
	dehnung = (float('1.'+ str(args.zentimeter)))
elif int(args.zentimeter) > 6:
	dehnung = (float('2.'+ str(args.zentimeter)))
elif int(args.zentimeter) > 7:
	dehnung = (float('2.'+ str(args.zentimeter)))
elif int(args.zentimeter) > 8:
	dehnung = (float('2.'+ str(args.zentimeter)))
else:
	dehnung = 1.0

#Position zählt die Gesamtabstaende auf, diff berechnet die Differenz zur nächsten Spalte
#abstand speichert den Abstand zwischen den Buchstaben
runde	= 0
position= 0.00
abstand = float(umfanggewickelt/float(args.zentimeter))+ dehnung

#Reihe speichert in welcher (aufgewickelten) Zeile man sich befindet
reihe = 0
#counter speichert die Spalte
counter = 0

for i in range(0,l,1):
	##Rundendaten und etwaige Differenz beim Spaltenübergang bestimmen
	if position >= 190:
		runde +=  1
		diff  = position - 190
		position = 0 + diff

##Wenn in jeder (aufgewickelten) Spalte ein Zeichen geschrieben wurde, gehe in die nächste Spalte
	if ((i % int(args.zentimeter)) == 0):
		reihe = 0
		counter += 1

	##Berechnung des Index des Zeichens innerhalb der zu übermittelnden Botschaft an der aktuellen Position
	zeichen = int(reihe*linelength+counter)


	##Zeichnen des Zeichens
	if ((i % int(args.zentimeter)) == 0):	
		TeXstring += r'''\node[rotate =-'''+ str(rotation) + r'''] at ('''+ str(runde) + r'''cm,-'''+ str(position) + r'''mm) {\huge{\StrChar{%(nachricht)s}{'''+ str(zeichen) + r'''}}};''' + "\n"
		##Zeichnen der Trennlinie
		TeXstring += r'''\draw ('''+ str(runde-0.5) + r'''cm,-'''+ str(position-abstand/2-1) + r'''mm) -- ++(1cm,-'''+ str(verschiebung) + r'''mm);''' + "\n"
	else:
		TeXstring += r'''\node[rotate =-'''+ str(rotation) + r'''] at ('''+ str(runde) + r'''cm,-'''+ str(position) + r'''mm) {\huge{\MakeUppercase{\randomstring}}};''' + "\n"
		##Zeichnen der Trennlinie
		TeXstring += r'''\draw ('''+ str(runde-0.5) + r'''cm,-'''+ str(position-abstand/2-1) + r'''mm) -- ++(1cm,-'''+ str(verschiebung) + r'''mm);''' + "\n"
	
	##Nächste Position zum Schreiben bestimmen
	position  += abstand
	reihe += 1

TeXstring += r'''\end{tikzpicture} \end{document} '''

#####################################################################
##randomstring.sty setzen
randomstring = r''' \ProvidesPackage{randomstring}[2014/11/06 v. 0.2]

\RequirePackage{ifxetex}

\newcommand{\setrandomstringlength}[1]{
  \chardef\rstr@length=#1\relax
}
\setrandomstringlength{26}

\ifxetex

  \input{random}
  \newcount\randomlen
  \newcount\randomletter

  \newcommand{\rstr@randomstring}[1]{
    \setrannum{\randomlen}{1}{\rstr@length}
    \loop\ifnum\randomlen>\z@
      \setrannum{\randomletter}{1}{26}
      #1
      \advance\randomlen\m@ne
    \repeat
  }

  \newcommand{\randomstring}{
    \rstr@randomstring{\@alph{\randomletter}}
  }
  \newcommand{\defrandomstring}[1]{
    \@ifdefinable#1{\def#1{}\rstr@randomstring{\rstr@add{#1}}}
  }
  \newcommand{\rstr@add}[1]{
    \edef#1{#1\@alph{\randomletter}}
  }

\else

  \newcommand{\randomstring}{
    \expandafter\rstr@generate\expandafter{\pdfuniformdeviate \rstr@length}
  }
  \newcommand{\rstr@generate}[1]{
    \expandafter\@alph\expandafter{\number\numexpr1+\pdfuniformdeviate 26}
    \ifnum#1>\z@
      \expandafter\@firstofone
    \else
      \expandafter\@gobble
    \fi
    {\expandafter\rstr@generate\expandafter{\number\numexpr#1-1}}
  }
  \newcommand{\defrandomstring}[1]{
    \@ifdefinable#1{\edef#1{\randomstring}}
  }

\fi

\endinput
'''

#Erstellen der .tex-Files, in die der jeweilige string geschrieben wird
with open('skytale.tex','w') as f:
    f.write(TeXstring%args.__dict__)
with open('randomstring.sty','w') as d:
    d.write(randomstring%args.__dict__)


#Aufruf von pdflatex
cmd = ['pdflatex', '-interaction', 'nonstopmode','-shell-escape', 'skytale.tex']
prozess = subprocess.Popen(cmd)
prozess.communicate()

#Überpruefung der Compilierung, eventuell Ausgabe der Exception
fehlercode = prozess.returncode
if not fehlercode == 0:
    raise ValueError('Fehler Nr. {} aufgetreten beim Aufruf von {}'.format(fehlercode, ' '.join(cmd)))
else:
	print('Nachricht wurde verschluesselt in "skytale.pdf" geschrieben')
	print('Insgesamt geschriebene Zeichen: ',i)
	print('Dehnung: ', dehnung)

#Verzeichnis aufräumen
os.unlink('skytale.tex')
os.unlink('skytale.log')
os.unlink('skytale.aux')
os.unlink('skytale.upa')
os.unlink('skytale.upb')
os.unlink('skytale.out')
os.unlink('randomstring.sty')


