# This file is part of xenharmlib.
#
# xenharmlib 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.
#
# xenharmlib 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 xenharmlib. If not, see <https://www.gnu.org/licenses/>.

"""
This module includes functions to export scales into the Scala .scl
file format, see https://www.huygens-fokker.org/scala/scl_format.html
"""

from typing import Optional
from ..core.protocols import PeriodicPitchScaleLike


def export_scl(
    filename: str,
    scale: PeriodicPitchScaleLike,
    title: Optional[str] = None,
    ensure_period: bool = False,
):
    """
    This function exports a pitch/note scale to a .scl file

    :param filename: Target filename to export data to
    :param scale: A pitch scale or note scale
    :param title: Title of the file (optional, defaults to the
        object representation of the scale)
    :param ensure_period: (optional, default False). If set to True
        the function will make sure that the first and the last
        item in the scale have the same pitch class. If this is
        not the case the function will append the next highest
        pitch/note that is equivalent to the first.
    """

    if title is None:
        title = repr(scale)

    title = title.replace('\n', '')
    title = title.replace('\r', '')

    if ensure_period and scale[0].pc_index != scale[-1].pc_index:
        scale = scale.union(scale.rotated_up())

    with open(filename, "w+") as f:

        f.write('! Scale generated by xenharmlib\n')
        f.write(f"{title}\n")

        # as per scl file specification the first pitch in the scale
        # maps to 0 and is considered implicit. that's why the count
        # is one smaller than the scale length. scales with only one
        # note have a count of 0

        count = len(scale) - 1
        f.write(f"{count}\n")

        current_cents = 0
        start = scale[0]

        for current in scale[1:]:

            # TODO: intervals should in the future indicate if they
            # are rational or irrational, so we can choose whether
            # to use fractions or cents in here

            interval = start.interval(current)
            rounded_cents = round(interval.cents, 6)
            f.write(f"{rounded_cents}\n")
