#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )

This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),

This application is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""

"""
This file handles various durations and their conversions.
"""


import logging; logger = logging.getLogger(__name__); logger.info("import")


from engine.config import METADATA

#Suggested import in other files:
#from template.engine.duration import DB, DL, D1, D2, D4, D8, D16, D32, D64, D128
#import template.engine.duration as duration


MAXIMUM_TICK_DURATION = 2**31-1


D4 = METADATA["quarterNoteInTicks"]
D8 = int(D4 / 2)
D16 = int(D8 / 2)
D32 = int(D16 / 2)
D64 = int(D32 / 2)
D128 = int(D64 / 2)
D256 = int(D128 / 2)
D512 = int(D256 / 2)
D1024 = int(D512 / 2) # set this to a number with many factors, like 210. According to http://homes.sice.indiana.edu/donbyrd/CMNExtremes.htm this is the real world limit.

if not int(D1024) == D1024:
    logger.error(f"Warning: Lowest duration D0124 has decimal places: {D1024} but should be a plain integer. Your D4 value: {D4} has not enough 2^n factors. ")

D2 = D4 *2
D1 = D2 *2
DB = D1 * 2  #Breve
DL = DB * 2  #Longa
DM = DL * 2  #Maxima


if not int(D128) == D128:
    raise ValueError(f"Durations must be integers (or .0). Yours: {D128}")


D_BASE_DURATIONS = (D1024, D512, D256, D64, D32, D16, D8, D4, D2, D1, DB, DL, DM)

#Duration Keywords
D_DEFAULT = 0
D_STACCATO = 1
D_TENUTO = 2
D_TIE = 3

def _baseDurationToTraditionalNumber(baseDuration):
    """4 = Quarter, 8 = Eighth, 0 = Brevis, -1= Longa
    Created in the loop below on startup"""
    if baseDuration == D4:
        return 4
    elif baseDuration == D8:
        return 8
    elif baseDuration == D16:
        return 16
    elif baseDuration == D2:
        return 2

    elif baseDuration == D1:
        return 1
    elif baseDuration == DB:
        return 0
    elif baseDuration == DL:
        return -1
    elif baseDuration == DM:
        return -2

    elif baseDuration == D32:
        return 32
    elif baseDuration == D64:
        return 64
    elif baseDuration == D128:
        return 128
    elif baseDuration == D256:
        return 256
    elif baseDuration == D512:
        return 512
    elif baseDuration == D1024:
        return 1024

    elif baseDuration == 0: #for KeySignatures and chords on init  etc.
        return 0
    else:
        raise ValueError("baseDuration does not match any traditioanl note duration value")

baseDurations = (0, D1024, D512, D256, D128, D64, D32, D16, D8, D4, D2, D1, DB, DL, DM) #from constants.py

baseDurationToTraditionalNumber = {}
for baseDuration in baseDurations:
    baseDurationToTraditionalNumber[baseDuration] = _baseDurationToTraditionalNumber(baseDuration)


traditionalNumberToBaseDuration = {}
for baseDuration in baseDurations:
    traditionalNumberToBaseDuration[_baseDurationToTraditionalNumber(baseDuration)] = baseDuration

def jackBBTicksToDuration(beatTypeAsTraditionalNumber, jackTicks, jackBeatTicks):
    if None in (beatTypeAsTraditionalNumber, jackTicks, jackBeatTicks):
        return None
    else:
        beatTypeDuration = traditionalNumberToBaseDuration[beatTypeAsTraditionalNumber]           
        #print (beatTypeAsTraditionalNumber, beatTypeDuration, jackTicks, jackBeatTicks)
        factor = beatTypeDuration / jackBeatTicks
        return jackTicks * factor
