import pathlib 
from django import http
from django.conf import settings
from django.urls import Resolver404, resolve
from django.utils.deprecation import MiddlewareMixin
from troggle import settings

"""Non-standard django middleware is loaded from this file.

"""
todo = """SmartAppendSlashMiddleware(object) Not Working. 
It needs re-writing. Can we make this work even though we have a catchall url rule ?
"""


class TroggleAppendSlashMiddleware(MiddlewareMixin):
    """
    "SmartAppendSlash" middleware for taking care of URL rewriting.

    This middleware appends a missing slash, if:
    * the SMART_APPEND_SLASH setting is True
    * the URL without the slash does not exist in urls.py
    * the URL with an appended slash does exist in urls.py
    Otherwise it won't touch the URL.
    
    MODIFICATION
    Since we have a universal catchall url pattern in urls.py, the usual way this works
    won't ever trigger adding a slash. So we check for the existence of a file in expoweb,
    not the existence of a pattern in urls.py...
    
    but site_media..
    but css etc....
    
    CONCLUSION
    This technique "works" but would be a maintence nightmare, so DO NOT USE IT
    do NOT include 
    troggle.core.middleware.TroggleAppendSlashMiddleware
    in settings.py 
    
    FURTHER WARNING
    If playing about with this, the 301 redirects that it creates will be cached INDEFINITELY by any browser you
    used to test it, e.g. /css/main.css with be permanetly redirected to /css/main2.css/ with dreadful 
    consequences, similarly for any images visited. You have to go into your browser settings and delete all cached
    files to recover from this.
    """

    def process_request(self, request):
        """Called for every url so return as quickly as possible
        Append a slash if TROGGLE_APPEND_SLASH is set, the resulting URL resolves and it doesn't without the /
        """
        if not settings.TROGGLE_APPEND_SLASH:
            return None

        if request.path.endswith("/"):
            return None

        if request.path.endswith("_edit"):
            return None
        
        if request.path.startswith("/"):
            relative_path = request.path[1:]
        else:
            relative_path = request.path
            
        for root in [settings.MEDIA_ROOT, settings.JSLIB_ROOT, settings.EXPOFILES, settings.SCANS_ROOT, settings.PHOTOS_ROOT]:
            full_path = root / relative_path
            print(f"+++++ MIDDLEWARE checking {root} / {relative_path} ")
            if full_path.is_file():
                print(f"+++++ MIDDLEWARE It IS a {root} file {full_path=} so use it as-is.")
                return None
            else:
                print(f"+++++ MIDDLEWARE NOT a {root}file {full_path=}")       

        host = http.HttpRequest.get_host(request)
        old_url = [host, request.path]
        # if _resolves(old_url[1]):
            # return None

        # So: it does not resolve according to our criteria, i.e. _edit doesn't count, and URL resolves doesn't count because of the catch all
        new_url = old_url[:]
        new_url[1] = new_url[1] + "/"
        if not _resolves(new_url[1]):
            print(f"+++++ MIDDLEWARE add SLASH and resolves {old_url=} => {new_url=}")
            return None
        else:
            if settings.DEBUG and request.method == "POST":
                # replace this exception with a redirect to an error page
                raise RuntimeError(
                    f"You called this URL via POST, but the URL doesn't end in a slash and you have SMART_APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to {new_url[0]}{new_url[1]} (note the trailing slash), or set SMART_APPEND_SLASH=False in your Django settings."
                )
        if new_url != old_url:
            # Redirect
            if new_url[0]:
                newurl = f"{request.is_secure() and 'https' or 'http'}://{new_url[0]}{new_url[1]}"
            else:
                newurl = new_url[1]
            if request.GET:
                newurl += "?" + request.GET.urlencode()
            return http.HttpResponsePermanentRedirect(newurl)

        return None


def _resolves(url):
    try:
        # If the URL does not resolve, the function raises a Resolver404 exception (a subclass of Http404)
        resolve(url)
        # this will ALWAYS be resolved by expopages because it will produce pagenotfound if not the thing asked for
        # so handle this in expopages, not in middleware
        return True
    except Resolver404:
        return False
    except:
        print(url)
        raise
