# -*- coding: utf-8 -*-
import http.server
import socketserver

from shutil import copyfile
from urllib.parse import unquote, urlparse

from logya.core import Logya
from logya.content import read, write_collection, write_page
from logya.template import env
from logya.util import filepath


class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
    """SimpleHTTPRequestHandler based class to return resources."""

    L = None

    def __init__(self, *args):
        super(HTTPRequestHandler, self).__init__(*args, directory=self.L.paths.public.as_posix())

    def do_GET(self):
        update_resource(self.path, self.L)
        super(HTTPRequestHandler, self).do_GET()


def get_collection_name(path, settings):
    for name, coll in settings['collections'].items():
        if path == coll['path']:
            return name


def update_resource(path, L):
    """Update resource corresponding to given url.

    Resources that exist in the `static` directory are updated if they are newer than the destination file.
    For other HTML resources the whole `L.index` is updated and the destination is newly written."""

    # Use only the actual path and ignore possible query params (see issue #3).
    url = unquote(urlparse(path).path)
    url_rel = path.lstrip('/')
    path_dst = filepath(L.paths.public, url)

    # If a static file is requested update it and return.
    src_static = L.paths.static.joinpath(url_rel)
    if src_static.is_file():
        dst_static = L.paths.public.joinpath(url_rel)
        dst_static.parent.mkdir(exist_ok=True)
        if not dst_static.exists() or src_static.stat().st_mtime > dst_static.stat().st_mtime:
            L.info(f'Update static resource: {dst_static}')
            copyfile(src_static, dst_static)
        return

    # Update content page.
    if content := L.index.get(url):
        content['doc'] = read(content['path'], content['path'].relative_to(L.paths.content))
        if L.collections:
            L.update_collections(content['doc'])
        # Always write doc because of possible template changes.
        write_page(path_dst, content, L.settings)
        L.info(f'Refreshed doc: {path}')

    # Update collection page.
    elif coll := L.collections.get(get_collection_name(url.split('/')[1], L.settings)):
        if content := coll['index'].get(url):
            write_collection(path_dst, content, L.settings)
            L.info(f'Refreshed collection: {path}')

    # Rebuild index for other HTML file requests.
    # elif url.endswith(('/', '.html', '.htm')):
    #     L.info(f'Rebuild site for request URL: {path}')
    #     L.build()


def serve(options):
    L = Logya(options)
    L.build()
    # Make Logya object accessible to server.
    HTTPRequestHandler.L = L

    # Make sure absolute links work.
    base_url = f'http://{options.host}:{options.port}'
    env.globals['base_url'] = base_url

    # Avoid "OSError: [Errno 98] Address already in use"
    socketserver.TCPServer.allow_reuse_address = True
    with socketserver.TCPServer((options.host, options.port), HTTPRequestHandler) as httpd:
        print(f'Serving on {base_url}')
        httpd.serve_forever()
@@ -832,16 +832,787 @@
  name%0A%0A%0A
+def update_page(url: str, L):%0A    %22%22%22Update content or collection page.%22%22%22%0A%0A    path_dst = filepath(L.paths.public, url)%0A%0A    if content := L.index.get(url):%0A        content%5B'doc'%5D = read(content%5B'path'%5D, content%5B'path'%5D.relative_to(L.paths.content))%0A        if L.collections:%0A            L.update_collections(content%5B'doc'%5D)%0A        # Always write doc because of possible template changes.%0A        write_page(path_dst, content, L.settings)%0A        L.info(f'Refreshed doc: %7Burl%7D')%0A        return True%0A%0A    if coll := L.collections.get(get_collection_name(url.split('/')%5B1%5D, L.settings)):%0A        if content := coll%5B'index'%5D.get(url):%0A            write_collection(path_dst, content, L.settings)%0A            L.info(f'Refreshed collection: %7Burl%7D')%0A            return True%0A%0A%0A
 def upda
@@ -2028,20 +2028,19 @@
 l_rel = 
-path
+url
 .lstrip(
@@ -2047,53 +2047,8 @@
 '/')
-%0A    path_dst = filepath(L.paths.public, url)
 %0A%0A  
@@ -2524,650 +2524,94 @@
 ent 
-page.%0A    if content := L.index.get(url):%0A        content%5B'doc'%5D = read(content%5B'path'%5D, content%5B'path'%5D.relative_to(L.paths.content))%0A        if L.collections:%0A            L.update_collections(content%5B'doc'%5D)%0A        # Always write doc because of possible template changes.%0A        write_page(path_dst, content, L.settings)%0A        L.info(f'Refreshed doc: %7Bpath%7D')%0A%0A    # Update collection page.%0A    elif coll := L.collections.get(get_collection_name(url.split('/')%5B1%5D, L.settings)):%0A        if content := coll%5B'index'%5D.get(url):%0A            write_collection(path_dst, content, L.settings)%0A            L.info(f'Refreshed collection: %7Bpath%7D')
+or collection existing in respective index.%0A    if update_page(url, L):%0A        return
 %0A%0A  
@@ -2627,16 +2627,18 @@
 ld index
+es
  for oth
@@ -2662,18 +2662,66 @@
 ests
+ and try again to update page in case of new content
 .%0A    
-# el
 if u
@@ -2756,26 +2756,24 @@
 .htm')):%0A   
- #
      L.info(
@@ -2809,21 +2809,18 @@
 L: %7B
-path
+url
 %7D')%0A   
- #
     
@@ -2830,16 +2830,44 @@
 build()%0A
+        update_page(url, L)%0A
 %0A%0Adef se

Create update_page function and rebuild site for requests HTML requests not found in any index.