package org.wikiwebserver.util;

import java.io.IOException;

import javax.sound.sampled.AudioFileFormat;

import org.wikiwebserver.core.WareHouse;
import org.wikiwebserver.handler.http.*;
import org.wikiwebserver.handler.http.interfaces.HTTPResponder;
import org.wikiwebserver.html.TemplatedPage;


public class Say implements HTTPResponder {
    
    
    public Object respond(HTTPHandler conn) throws IOException {
        
        String text = null;

        FormData formData = conn.getRequest().getFormData();
        if (formData != null) text = formData.getFirst("text");
        
        return respond(text, conn);        
    }

    public Object respond(String text, HTTPHandler conn) throws IOException {
        
        if (text == null) {
            return "<form><input name='text' value='Welcome to WikiWebServer'>" +
                   "<input type='hidden' name='type' value='audio/x-wav'>" + 
                   "<input type='submit' name='action' value='Say'></form>";
        } 
  
        
        if (text.length() > 512) {
            
            // If this is a lot of text, split and return m3u
            StringBuilder m3u = new StringBuilder();
            
            int start = 0;
            while (text.length() > start) {
                int end = text.lastIndexOf('.', start + 512);
                if (end == -1) end = text.length();                
                if (end < start) break;
                String chunk = text.substring(start, end);
                String url = getSpeechUrl(chunk, conn);
                m3u.append(url);
                m3u.append("\r\n");
                start = end+1;
            }
            
            conn.getResponse().getHeaders().set("Content-Type", "audio/x-mpegurl");
            return m3u.toString();
        }            
        

        // Default audio format
        String contentType = "audio/x-wav";
        AudioFileFormat.Type format = AudioFileFormat.Type.WAVE;
        
        FormData formData = conn.getRequest().getFormData();                   
        if (formData != null) {
            String reqType = formData.getFirst("type");               
            if (reqType != null && reqType.equals("aiff")) {
                contentType = "audio/aiff";
                format = AudioFileFormat.Type.AIFF;
            } 
            else if (reqType != null && reqType.equals("au")) {
                contentType = "audio/x-au";
                format = AudioFileFormat.Type.AU;
            }     
        }
        
        prepairStream(conn, contentType);
        SpeechHelper speaker = SpeechHelper.getInstance(); 
        
        byte[] soundData = speaker.getSoundData(text, format);
        
        if (soundData.length == 0) {
            throw new HTTPException(500, "No speech data returned");
        }
        
        return soundData;
    }   
    
    public static String getSpeechUrl(String text, HTTPHandler conn) {
        
        String audioFormat = "wav";
        
        String userAgent = conn.getRequest().getHeaders().getFirst("User-Agent");        
        if (userAgent != null && userAgent.contains("Safari")) audioFormat = "aiff";

        return conn.getServiceAddress() + WareHouse.getUrlPathForClass(Say.class) + 
               "?type=" + audioFormat + "&text=" + WareHouse.formDataEncode(text);
    }
    
    public static void addSpeechToPage(String text, TemplatedPage page) {

        String userAgent = page.getRequest().getHeaders().getFirst("User-Agent");
        String url = getSpeechUrl(text, page.getHandler());
        
        if (userAgent != null && userAgent.contains("MSIE")) {  
            page.appendToHead("<bgsound src='" + url + "'>"); 
        } else {          
            page.append("<embed src='" + url + "' hidden='true' autostart='true' loop='false' />");                   
        }
    } 
    
    private void prepairStream(HTTPHandler conn, String type) {
        HTTPHeaders headers = conn.getResponse().getHeaders();
        
        headers.set("Content-Type", type);
        long time = System.currentTimeMillis();
        headers.setDate("Last-Modified", time);
        long expires = time + 7 * 24 * 60 * 60 * 1000;
        headers.setDate("Expires", expires);
        headers.set("Pragma", "cache");
        headers.set("Cache-Control", "public");            
    }
}
