"""
The logic for writing shared files.
"""

import os
import os.path

import pkg_resources
from six.moves import cStringIO
from six.moves import configparser

from edx_lint import __version__
from edx_lint.configfile import merge_configs
from edx_lint.tamper_evident import TamperEvidentFile
from edx_lint.metadata import KNOWN_FILES


def make_header(metadata, filename, tweaks_name):
    """Construct the appropriate header warning for `filename`.

    (Sorry about the logic here, I didn't want to install Jinja just for this.)
    """

    header = """\
***************************
** DO NOT EDIT THIS FILE **
***************************

This file was generated by edx-lint: https://github.com/openedx/edx-lint

"""
    if tweaks_name:
        header += """\
If you want to change this file, you have two choices, depending on whether
you want to make a local change that applies only to this repo, or whether
you want to make a central change that applies to all repos using edx-lint.

Note: If your {filename} file is simply out-of-date relative to the latest
{filename} in edx-lint, ensure you have the latest edx-lint installed
and then follow the steps for a "LOCAL CHANGE".

LOCAL CHANGE:

1. Edit the local {tweaks_name} file to add changes just to this
   repo's file.

2. Run:

      $ edx_lint write {filename}

3. This will modify the local file.  Submit a pull request to get it
   checked in so that others will benefit.

"""
    else:
        header += """\
If you want to change this file, you must edit the central file in the
edx-lint repo.

Note: If your {filename} file is simply out-of-date relative to the latest
{filename} in edx-lint, ensure you have the latest edx-lint installed
and then run:

      $ edx_lint write {filename}

"""
    header += """\

CENTRAL CHANGE:

1. Edit the {filename} file in the edx-lint repo at
   https://github.com/openedx/edx-lint/blob/master/edx_lint/files/{filename}

2. install the updated version of edx-lint (in edx-lint):

      $ pip install .

3. Run (in edx-lint):

      $ edx_lint write {filename}

4. Make a new version of edx_lint, submit and review a pull request with the
   {filename} update, and after merging, update the edx-lint version and
   publish the new version.

5. In your local repo, install the newer version of edx-lint.

6. Run:

      $ edx_lint write {filename}

7. This will modify the local file.  Submit a pull request to get it
   checked in so that others will benefit.





STAY AWAY FROM THIS FILE!





SERIOUSLY.

------------------------------
Generated by edx-lint version: {version}
------------------------------
"""
    text = header.format(filename=filename, tweaks_name=tweaks_name, version=__version__)
    text = "".join((metadata.comment.format(line).rstrip() + "\n") for line in text.splitlines())
    return text


def write_file(filename, output_fn):
    """Write `filename`.

    Messages go to `output_fn`.  Return value is an exit status for the
    main command to exit with.
    """
    metadata = KNOWN_FILES.get(filename)
    if metadata is None:
        output_fn("Don't have file %r to write." % filename)
        return 2

    if os.path.exists(filename):
        output_fn("Checking existing copy of %s" % filename)
        tef = TamperEvidentFile(filename)
        if not tef.validate():
            bak_name = amend_filename(filename, "_backup")
            output_fn("Your copy of %s seems to have been edited, renaming it to %s" % (filename, bak_name))
            if os.path.exists(bak_name):
                output_fn("A previous %s exists, deleting it" % bak_name)
                os.remove(bak_name)
            os.rename(filename, bak_name)

    output_fn("Reading edx_lint/files/%s" % filename)

    file_content = get_file_content(filename)

    tweaks_name = None
    if metadata.format == "ini":
        cfg = configparser.RawConfigParser()
        cfg.read_string(file_content, f"<internal {filename}>")

        tweaks_name = amend_filename(filename, "_tweaks")
        if os.path.exists(tweaks_name):
            output_fn("Applying local tweaks from %s" % tweaks_name)
            cfg_tweaks = configparser.RawConfigParser()
            cfg_tweaks.read([tweaks_name])

            merge_configs(cfg, cfg_tweaks)

    output_fn("Writing %s" % filename)
    output_text = cStringIO()
    output_text.write(make_header(metadata=metadata, filename=filename, tweaks_name=tweaks_name))
    if metadata.format == "ini":
        cfg.write(output_text)
    else:
        output_text.write(file_content)

    out_tef = TamperEvidentFile(filename)
    output_bytes = output_text.getvalue().encode("utf8")
    out_tef.write(output_bytes, hashline=metadata.comment)

    return 0


def get_file_content(filename):
    """Get the contents of the file that should be written."""
    return pkg_resources.resource_string("edx_lint", f"files/{filename}").decode("utf8")


def amend_filename(filename, amend):
    """Amend a filename with a suffix.

    amend_filename("foo.txt", "_tweak") --> "foo_tweak.txt"

    """
    base, ext = os.path.splitext(filename)
    amended_name = base + amend + ext
    return amended_name
