package page.tools.html;

import static org.wikiwebserver.html.HTMLHelper.javaScript;

import java.io.IOException;
import java.net.SocketException;

import org.wikiwebserver.handler.http.HTTPException;
import org.wikiwebserver.handler.http.HTTPHandler;
import org.wikiwebserver.handler.http.interfaces.HTTPResponder;

import page.config.SiteTemplatedPage;

public abstract class TemplatedPushPage extends SiteTemplatedPage implements HTTPResponder {
    
    private boolean enabled = false;
    
    protected void setPushEnabled(boolean enabled) {
        this.enabled = enabled;      
    }

    protected abstract void generate() throws HTTPException;
    
    public Object respond(HTTPHandler conn) throws IOException {
        
        // First send the initial page
        Object initialPage = super.respond(conn);

        // Push not enabled, return content
        if (!enabled) return initialPage;
        
        // Disable content encoding as it will slow things down client side
        getResponse().getHeaders().set("Content-Encoding", "none");
        getWriter().write(initialPage);
        
        // Stop updating after 10 minutes to prevent bandwidth consumption
        int delay = 600000;
        try {
             delay = Integer.parseInt(getFormData().getFirst("timeout"));
        } catch (Exception ignored) {}

        if (delay > 0) {
            String safe = getServiceAddress();
            getWriter().write(javaScript("setTimeout(\"window.location='" + safe + "'\", " + delay + ");"));  
        }

        getWriter().flush();
        
        // Get ready to begin pushing more data
        clearBody();
        try {
            begin();
            
            flush();
            
            // Now push more data until finished or client disconnects
            // (Client disconnection will throw exception on next write)
            run();
          
        } catch (SocketException ex) {
            // Ignore client disconnection (expected)     
        } catch (Throwable ex) {
            ex.printStackTrace();
        } finally {
            cleanup();
        }
        
        // Finished pushing gracefully!
        return null;
    }
    
    protected void run() throws IOException {      
        while (enabled) {
            // Periodically push new data
            update();
            flush();
            if (enabled) {
                try { Thread.sleep(getUpdatePeriod()); } 
                catch (Exception ex) {}
            }
        }
    }
    
    /**
     * Set things up ready for pushing
     */
    protected void begin() throws IOException {
        
    }
    
    /**
     * Update stuff on the page by pushing javascript
     */    
    protected abstract void update() throws IOException;
    
    /**
     * Perform required cleanup operations as a result of an
     * the client closing the connection or an error occuring.
     */    
    protected void cleanup() throws IOException {

    }    

    public void flush() throws IOException {
        getWriter().write(getBody() + "\r\n");
        getWriter().flush();
        clearBody();
    }
}
