# -*- coding: UTF-8 -*-

"""
VERSION: 0.1    2022
AUTHOR: RASCADINO. 
LICENSE: GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007. 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.

Scribus Version >= 1.5.8 Mac

Download Scribus 1.5.8 (scribus-devel)
https://sourceforge.net/projects/scribus/files/scribus-devel/1.5.8/

Nutzung:

!!! Das Script wurde nur unter MacOs 12.x getestet. 
!!! Zum Verhalten in andern Betriebssystemen kann vom Autor keine Aussage getroffen werden.

Aufruf im Terminal: /Applications/Scribus.app/Contents/MacOS/Scribus -g -ns -py /pfad/zu/deinem/kalendersript.py
Aufruf in Scribus:  Menü 'Scrip' -> 'Script ausführen...

Falls Module nicht vorhanden sind, können diese wie folgt installiert werden:
/Applications/Scribus.app/Contents/Frameworks/Python.framework/Versions/3.9/bin/pip3 install modulname

Kalenderbilder: 
Bilder numerisch nach den Monaten benennen: 01.jpg, ... 12.jpg
Nur JPGs mit der Erweiterung . jpg
Alle 12 Bilder in einen Ordner speichern

Nach dem Scriptaufruf poppen Dialoge auf mit den Fragen nach:
    - Kalenderformat, DIN A3 oder DIN A2
    - Kalenderjahr
    - Ordner der Kalenderbilder
    - unter welchem Namen soll der Kalender gespeichert werden (gespeichert wird als Scribus *.sla)
    - Speicherort
    - Copyright Inhaber

Achtung!
Das Speichern der PDF-Datei kann je nach Maschine einige Zeit dauern. Wenn sich Scribus von selbst 
schließt ist der Vorgang in der Regel abgeschlossen. Etwas Geduld haben!
"""

#imports
import calendar
from calendar import monthrange
import locale
import datetime
from datetime import datetime, timedelta, date
import platform
import pandas as pd
import sys
import time

try:
    import scribus
except ImportError:
    print("Dieses Python-Script läuft nur innerhalb des Scribus scripting interface.")
    print("Aufruf via Command Line oder direkt aus Scribus Menü Script -> Script ausführen..!")
    sys.exit(1)

os = platform.system()
if os != "Darwin":
    print("Dein Betriebssystem wird wahrscheinlich nicht unterstützt! Getestet nur nur für MAC OS.")
    scribus.messageBox("OS error", "Dein Betriebssystem wird wahrscheinlich nicht unterstützt! Getestet nur für MAC OS.", scribus.ICON_INFORMATION)
    #sys.exit(1)

todays_date = date.today()
nextYear = int(todays_date.year) + 1

# Dialog-Boxen zur Personalisierung
calFormat        = scribus.valueDialog('Kalenderformat', 'Kalenderformt DIN A3 ODER DIN A2', "A2")
year            = scribus.valueDialog('Kalenderjahr', 'Bitte Kalenderjahr eingeben', str(nextYear))
calName         = scribus.valueDialog('Name Deines Kalenders, ohne Erweiterung', 'Dateiname', 'meinTollerKalender')
copyrightOwner  = scribus.valueDialog('Cpyright Inhaber', 'Copyright', 'Max Mustermann')
calImagePath    = scribus.fileDialog('Ordner Deiner Kalenderbilder auswählen', "Bilder", isdir=1)
calPath         = scribus.fileDialog('Ordner auswählen, in dem Dein Kalender gespeichert wird', "Ordner auswählen", isdir=1)
calPathName     = calPath + "/" + calName + ".sla"
year            = int(year)
calImagePath    = calImagePath + "/"

# Parameter
calImageExt     = ".jpg"                                         # Dateierweiterung der Bilder
fontDefault     = "SF Pro Text Ultralight"                       # https://github.com/sahibjotsaggu/San-Francisco-Pro-Fonts/blob/master/SF-Pro-Text-Ultralight.otf
black           = "#282728"                                      # in Scribus anlegen CMYK
cyan            = 'Cyan'
grau            = '#7e7e7e'                                      # in Scribus anlegen CMYK
copyright       = u"\xa9 " + str(year) + " " + copyrightOwner
monat           = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]
jahrZeitAnfang  = [["2022", ["2022-03-20", "2022-06-21", "2022-09-23", "2022-12-21"]], ["2023", ["2023-03-20", "2023-06-21", "2023-09-23", "2023-12-21"]], ["2024", ["2024-03-20", "2024-06-20", "2024-09-22", "2024-12-21"]], ["2025", ["2025-03-20", "2025-06-21", "2025-09-22", "2025-12-21"]], ["2026", ["2026-03-20", "2026-06-21", "2026-09-22", "2026-12-21"]], ["2027", ["2027-03-20", "2027-06-21", "2027-09-23", "2027-12-22"]], ["2028", ["2028-03-20", "2028-06-20", "2028-09-23", "2028-12-21"]], ["2029", ["2029-03-20", "2029-06-21", "2029-09-22", "2029-12-21"]], ["2030", ["2030-03-20", "2030-06-21", "2030-09-22", "2030-12-21"]]]

# Ab hier nichts mehr ändern!
###########################################################################################################################################################################
if(calFormat == "A2"):
    print("A2")
    formatB         = 594           # DIN A2 Breite
    formatH         = 420           # DIN A2 Höhe
    datBoxB         = 13
    datBoxH         = 8.5
    datBoxStartX    = 13.6
    datBoxY         = 400.5
    datBoxFontSize  = 20
    holBoxX         = 16.8
    holBoxY         = 410.5
    holBoxB         = 400
    holBoxH         = 5
    holFontSize     = 9
    mBoxX           = 488
    mBoxY           = 397.5
    mBoxB           = 90
    mBoxH           = 15
    mBoxFontSize    = 30
    lineBoxStartY   = 397.6
    lineBoxEndY     = 407.1
    lineBoxWidth    = 0.035
    wnTextBoxY      = lineBoxStartY - 1
    wnTextBoxB      = 6
    wnTextBoxH      = 6
    wnTextBoxFontSize = 10
    iBoxX           = 17
    iBoxY           = 17
    iBoxB           = 560
    iBoxH           = 560 / 1.5
    tBoxXstart      = 10
    tBoxB           = 143
    tBoxH           = 143 / 1.5
    tBoxY           = 53
    yBoxX           = 0
    yBoxY           = 364
    yBoxB           = formatB
    yBoxH           = 25
    cBoxX           = 0
    cBoxY           = 386
    cBoxB           = formatB
    cBoxH           = 6
else:
    print("A3")
    formatB         = 420           # DIN A3 Breite
    formatH         = 297           # DIN A3 Höhe
    datBoxB         = 10.5
    datBoxH         = 8.5
    datBoxStartX    = 26
    datBoxY         = 271
    datBoxFontSize  = 18
    holBoxX         = 28.25
    holBoxY         = 286
    holBoxB         = 285
    holBoxH         = 5
    holFontSize     = 9
    mBoxX           = 362.25
    mBoxY           = datBoxY
    mBoxB           = 30
    mBoxH           = 8.5
    mBoxFontSize    = 18
    lineBoxStartY   = 267.5
    lineBoxEndY     = 277
    lineBoxWidth    = 0.035
    wnTextBoxY      = lineBoxStartY - 1
    wnTextBoxB      = 6
    wnTextBoxH      = 6
    wnTextBoxFontSize = 10
    iBoxX           = 28.15
    iBoxY           = 17
    iBoxB           = 363.9
    iBoxH           = 242.6
    tBoxXstart      = 10
    tBoxY           = 40
    tBoxB           = 100
    tBoxH           = 100 / 1.5
    yBoxX           = 0
    yBoxY           = 258
    yBoxB           = formatB
    yBoxH           = 25
    cBoxX           = 0
    cBoxY           = 280
    cBoxB           = formatB
    cBoxH           = 6
#sys.exit()
#################################
# functions
#################################

def feiertage(year):
    A = year % 19
    K = year // 100
    M = 15 + (3 * K + 3) // 4 - ( 8 * K + 13) // 25
    D = (19 * A + M) % 30
    S = 2 - (3 * K + 3) // 4
    R = D // 29 + (D // 28 - D // 29) * (A // 11)
    OG = 21 + D + R
    SZ = 7 - (year + year // 4 + S) % 7
    OE = 7 - (OG - SZ) % 7
    OS = (OG + OE)
    if OS > 31:
        os = str(year) + "-04-" + str(OS-31)
        kf = str(year) + "-04-" + str(OS-33)
        om = str(year) + "-04-" + str(OS-30)
    else:
        os = str(year) + "-04-" + str(OS)
        kf = str(year) + "-04-" + str(OS-2)
        om = str(year) + "-04-" + str(OS+1)
    easter = [
        [kf, "Karfreitag", 0],
        [os, str("Ostersonntag"), 1],
        [om, "Ostermontag", 1]
    ]
    oss = easter[1][0].split('-')
    himf = datetime(int(oss[0]), int(oss[1]), int(oss[2])) + timedelta(days = 40)
    himf = str(himf).split(' ')
    easter.append([himf[0], "Christi Himmelfahrt", 1])
    pfso = datetime(int(oss[0]), int(oss[1]), int(oss[2])) + timedelta(days = 49)
    pfso = str(pfso).split(' ')
    easter.append([pfso[0], "Pfingstsonntag", 1])
    pfmo = datetime(int(oss[0]), int(oss[1]), int(oss[2])) + timedelta(days = 50)
    pfmo = str(pfmo).split(' ')
    easter.append([pfmo[0], "Pfingstmontag", 0])
    frln = datetime(int(oss[0]), int(oss[1]), int(oss[2])) + timedelta(days = 60)
    frln = str(frln).split(' ')
    easter.append([frln[0], "Fronleichnam", 0])
    rosm = datetime(int(oss[0]), int(oss[1]), int(oss[2])) - timedelta(days = 48)
    rosm = str(rosm).split(' ')
    easter.append([rosm[0], "Rosenmontag", 0])
    sont = datetime(year, 12, 24).weekday()
    if sont != 6:           # 24.12. ist kein Sonntag
        diff4 = sont + 1
        adv4 = datetime(year, 12, 24) - timedelta(int(diff4))
        adv4 = str(adv4).split(' ')
        diff3 = diff4 + 7
        adv3 = datetime(year, 12, 24) - timedelta(int(diff3))
        adv3 = str(adv3).split(' ')
        diff2 = diff4 + 14
        adv2 = datetime(year, 12, 24) - timedelta(int(diff2))
        adv2 = str(adv2).split(' ')
        diff1 = diff4 + 21
        adv1 = datetime(year, 12, 24) - timedelta(int(diff1))
        adv1 = str(adv1).split(' ')
    else:                   # 24.12. ist Sonntag
        adv4 = str(year) + '-12-24'
        adv3 = datetime(year, 12, 24) - timedelta(7)
        adv3 = str(adv3).split(' ')
        adv2 = datetime(year, 12, 24) - timedelta(14)
        adv2 = str(adv2).split(' ')
        adv1 = datetime(year, 12, 24) - timedelta(21)
        adv1 = str(adv1).split(' ')
    easter.append([adv1[0], "1. Advent", 0])
    easter.append([adv2[0], "2. Advent", 0])
    easter.append([adv3[0], "3. Advent", 0])
    easter.append([adv4[0], "4. Advent", 0])
    easter.append([str(year) + "-12-24", "Heiligabend", 0])
    easter.append([str(year) + "-12-25", "Weihnachten", 1])
    easter.append([str(year) + "-12-26", "2. Weihnachtstag", 1])
    easter.append([str(year) + "-01-01", "Neujahr", 1])
    easter.append([str(year) + "-02-14", "Valentinstag", 0])
    easter.append([str(year) + "-05-01", "Tag der Arbeit", 1])
    easter.append([str(year) + "-08-15", "Mariä Himmelfahrt", 0])
    easter.append([str(year) + "-10-03", "Tag der Deutschen Einheit", 1])
    for x in jahrZeitAnfang:
        if x[0] == str(year):
            easter.append([x[1][0], "Frühlingsanfang", 0])
            easter.append([x[1][1], "Sommeranfang", 0])
            easter.append([x[1][2], "Herbstanfang", 0])
            easter.append([x[1][3], "Winteranfang", 0])
    return(easter)

def daysInMonth(year):
    dim = []
    for m in range(1, 13):
        dim.append(monthrange(year, m)[1])
    return (dim)

def compCal(year):
    cal = []
    m = 1
    dpm = daysInMonth(year)
    for d in dpm:
        n = m - 1
        cal.append([m])
        for r in range(1, d + 1):
            dat = str(year) + "-" + str(m).zfill(2) + "-" + str(r).zfill(2)     # Datum
            ts = pd.Timestamp(dat)
            dna = ts.dayofweek                                                  # Wochentag
            d1 = ""
            d2 = 0
            d3 = ""
            for f in feiertage(year):                                           # Feiertag?
                if str(dat) == str(f[0]):
                    d1 = str(f[1])
                    d2 = str(f[2])
            ts = pd.Timestamp(int(year), int(m), int(r))
            d3 = str(ts.week).zfill(2)
            cal[n].append([dat, dna, d1, d2, d3])                               # [monat[datum, wochentag, feiertagname, bundesweit, kalenderwoche], ...], ...
        m += 1
    return(cal)

############################
# Scribus Code
############################

def baueKalender(year): 
    calenda = compCal(year)
    #print(calenda)
    #sys.exit()
    scribus.newDocument((formatH, formatB), (0, 0, 0, 0), scribus.LANDSCAPE, 1, scribus.UNIT_MILLIMETERS, scribus.PAGE_1, 12, 1)
    scribus.createLayer("Bilder")
    scribus.createLayer("Text")
    for z in range(0, 11):
        scribus.newPage(-1)

    for p in range(scribus.pageCount()):
        m  =  p + 1
        print("Baue Blatt " + str(m))
        scribus.gotoPage(m)
        fText = ""
        for n in range(len(calenda[p])):
            if len(str(calenda[p][n])) > 2:
                if len(str(calenda[p][n][2])) > 0:
                    part = str(calenda[p][n][0]).split('-')
                    fDat = part[2] + "." + part[1] + ". "
                    fText = fText + str(fDat) + str(calenda[p][n][2]) + " " + u"\xb7 "
                dat = str(calenda[p][n][0]).split("-")
                if n > 1:
                    datBoxX = (datBoxB * (n - 1)) + datBoxStartX
                else:
                    datBoxX = datBoxStartX
                dBox = scribus.createText(datBoxX, datBoxY, datBoxB, datBoxH)
                scribus.setText(dat[2], dBox)
                scribus.setFont(fontDefault, dBox)
                scribus.setFontSize(datBoxFontSize, dBox)
                scribus.setTextAlignment(scribus.ALIGN_CENTERED, dBox)
                scribus.sendToLayer("Text" , dBox)
                if int(calenda[p][n][1]) > 5 or int(calenda[p][n][3]) > 0:
                    color = cyan
                else:
                    color = black
                scribus.setTextColor(color, dBox)
                #Wochennummer
                if int(calenda[p][n][1]) < 1:
                    # Trennlinie
                    wnLine = scribus.createLine(datBoxX, lineBoxStartY, datBoxX, lineBoxEndY)
                    scribus.setLineWidth(lineBoxWidth, wnLine)
                    scribus.setLineColor(grau, wnLine)
                    scribus.sendToLayer("Text", wnLine)
                    # Wochennummer
                    wnTxt = scribus.createText(datBoxX + 1, wnTextBoxY, wnTextBoxB, wnTextBoxH)
                    scribus.setText(str(calenda[p][n][4]), wnTxt)
                    scribus.setFont(fontDefault, wnTxt)
                    scribus.setFontSize(wnTextBoxFontSize, wnTxt)
                    scribus.setTextColor(grau, wnTxt)
                    scribus.setTextAlignment(scribus.ALIGN_CENTERED, wnTxt)
                    scribus.sendToLayer("Text", wnTxt)
        # Zeile Feiertage
        fText = fText[:-3]
        fBox = scribus.createText(holBoxX, holBoxY, holBoxB, holBoxH)
        scribus.setText(fText, fBox)
        scribus.setFont(fontDefault, fBox)
        scribus.setFontSize(holFontSize, fBox)
        scribus.setTextColor(grau, fBox)
        scribus.setTextAlignment(scribus.ALIGN_LEFT, fBox)
        # Zeile Monat Jahr
        mBox = scribus.createText(mBoxX, mBoxY, mBoxB, mBoxH)
        if calFormat == "A2":
            scribus.setText(monat[p] + " " + u"\xb7" + " " + str(year), mBox)
        else:
            scribus.setText(str(m).zfill(2) + " " + u"\xb7" + " " + str(year), mBox)
        scribus.setFont(fontDefault, mBox)
        scribus.setFontSize(mBoxFontSize, mBox)
        scribus.setTextColor(black, mBox)
        scribus.setTextAlignment(scribus.ALIGN_RIGHT, mBox)
        # Bilder
        iBox = scribus.createImage(iBoxX, iBoxY, iBoxB, iBoxH)
        imgName = str(m).zfill(2) + str(calImageExt)
        scribus.loadImage( calImagePath + imgName, iBox)
        scribus.setScaleImageToFrame(1,1,iBox)
        scribus.sendToLayer("Bilder" , iBox)
    # Deckblatt
    print("Baue Deckblatt")
    scribus.newPage(1)
    # Hintergrund
    tBackGroud = scribus.createRect(10, tBoxY, tBoxB * 4, tBoxH * 3)
    scribus.setFillColor(grau, tBackGroud)
    scribus.sendToLayer("Bilder", tBackGroud)
    scribus.selectObject(tBackGroud)
    scribus.moveSelectionToBack()
    scribus.deselectAll()
    # Bilder
    for i in range(0, 12):
        if i < 4:                           # 1. Reihe Bilder
            xt = tBoxXstart + i * tBoxB
            yt = tBoxY
        elif i > 3 and i < 8:               # 2. Reihe Bilder
            xt = 10 + (i - 4) * tBoxB
            yt = tBoxY + tBoxH
        elif i > 7:                         # 3. Reihe Bilder
            xt = 10 + (i - 8) * tBoxB
            yt = tBoxY + 2 * tBoxH
        z = i + 1
        iBox = scribus.createImage(xt, yt, tBoxB, tBoxH)
        tName = str(z).zfill(2) + str(calImageExt)
        scribus.loadImage( calImagePath + tName, iBox)
        scribus.setScaleImageToFrame(1,0,iBox)
        scribus.setScaleImageToFrame(0,1,iBox)
        scribus.sendToLayer("Bilder" , iBox)
    # Jahreszahl
    yBox = scribus.createText(yBoxX, yBoxY, yBoxB, yBoxH)
    scribus.setText(str(year), yBox)
    scribus.setFont(fontDefault, yBox)
    scribus.setFontSize(50, yBox)
    scribus.setTextColor(black, yBox)
    scribus.setTextAlignment(scribus.ALIGN_CENTERED, yBox)
    # copyright
    cBox = scribus.createText(cBoxX, cBoxY, cBoxB, cBoxH)
    scribus.setText(copyright, cBox)
    scribus.setFont(fontDefault, cBox)
    scribus.setFontSize(12, cBox)
    scribus.setTextColor(black, cBox)
    scribus.setTextAlignment(scribus.ALIGN_CENTERED, cBox)
    # Dokument speichern (.sla)
    scribus.saveDocAs(calPathName)
    # PDF
    pdf = scribus.PDFfile()
    pdf.file = calPath + "/" + calName + ".pdf"
    pdf.save()

# Script Auftruf
######################################################
def main():
    """ Application/Dialog loop with Scribus sauce around """
    try:
        scribus.statusMessage('Running script...')
        scribus.progressReset()
        app = baueKalender(year)
    finally:
        if scribus.haveDoc() > 0:
            scribus.redrawAll()
        scribus.statusMessage('Done.')
        scribus.progressReset()

if __name__ == '__main__':
    main()