package org.bucksch.zeipis.importer;
import org.bucksch.zeipis.all.*;
import org.w3c.dom.*;
import java.sql.*;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

public class LineupExporter
{
  protected PreparedStatement findStations;
  protected PreparedStatement findChannels;
  protected void createSQLStatements()
    throws SQLException
  {
    findStations = DB.me.database().prepareStatement("SELECT stationid, preset, long_name, short_name, xmltvid, icon, station_group, commercial_free FROM station WHERE xmltvid is not null ORDER BY preset");
    findChannels = DB.me.database().prepareStatement("SELECT channeltype, tech_name, dvb_provider_name, dvb_serviceid, transportid, networkid, dvb_encrypted, languages, xmltvid FROM channel LEFT JOIN station USING (stationid) LEFT JOIN dvb_transponder USING (dvb_transponderid) WHERE xmltvid is not null");
  }
  public LineupExporter()
    throws Exception
  {
    // Init DB and create XML DOM
    new DB();
    createSQLStatements();
    Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
    doc.appendChild(doc.createElement("lineup"));

    // Station list
    Element stations = (Element) doc.getDocumentElement().appendChild(doc.createElement("stations"));
    ResultSet rs = findStations.executeQuery();
    while (rs.next())
    {
      try {
        //Util.debug("station " + rs.getString("long_name"));
        if ( ! hasValue(rs.getString("xmltvid"))) continue;
        if ( ! hasValue(rs.getString("long_name"))) continue;
        if ( ! hasValue(rs.getString("short_name"))) continue;
        Element station = doc.createElement("station");
        station.setAttribute("rfc2838id", rs.getString("xmltvid"));
        writeTextElement(station, rs, rs.getString("long_name"), "long-name");
        writeTextElement(station, rs, rs.getString("short_name"), "short-name");
        writeTextElement(station, rs, rs.getString("preset"), "preset");
        if (hasValue(rs.getString("icon")))
        {
          Element logo = (Element) station.appendChild(doc.createElement("logo"));
          logo.setAttribute("url", rs.getString("icon"));
        }
        writeTextElement(station, rs, rs.getString("station_group"), "group");
        writeTextElement(station, rs, rs.getBoolean("commercial_free") ? "true" : "false", "commercial-free");
        stations.appendChild(station);
      } catch (Exception e) { Util.error("station failed", e); }
    }

    // map channel -> station
    Element channels = (Element) doc.getDocumentElement().appendChild(doc.createElement("channels"));
    rs = findChannels.executeQuery();
    while (rs.next())
    {
      try {
        if (rs.getString("channeltype").equals("DVB"))
        {
          //Util.debug("channel " + rs.getString("tech_name"));
          if ( ! hasValue(rs.getString("xmltvid"))) continue;
          if ( ! hasValue(rs.getString("tech_name"))) continue;
          Element channel = doc.createElement("dvb-channel");
          channel.setAttribute("rfc2838id", rs.getString("xmltvid"));

          Element name = (Element) channel.appendChild(doc.createElement("dvb-name"));
          name.setAttribute("service", rs.getString("tech_name"));
          if (hasValue(rs.getString("dvb_provider_name")))
            name.setAttribute("provider", rs.getString("dvb_provider_name"));

          if (rs.getInt("dvb_serviceid") != 0 && rs.getInt("transportid") != 0 && rs.getInt("networkid") != 0)
          {
            Element id = (Element) channel.appendChild(doc.createElement("dvb-id"));
            id.setAttribute("service", rs.getString("dvb_serviceid"));
            id.setAttribute("transport", rs.getString("transportid"));
            id.setAttribute("network", rs.getString("networkid"));
          }

          writeTextElement(channel, rs, rs.getBoolean("dvb_encrypted") ? "true" : "false", "encrypted");
          channels.appendChild(channel);
        }
      } catch (Exception e) { Util.error("channel failed", e); }
    }

    // Output XML doc
    //doc.normalizeDocument();
    /*
    DOMImplementation implementation = DOMImplementationRegistry.newInstance().getDOMImplementation("XML 3.0");
    DOMImplementationLS feature = (DOMImplementationLS) implementation.getFeature("LS", "3.0");
    LSSerializer serializer = feature.createLSSerializer();
    //serializer.getDomConfig().setParameter("format-pretty-print", "true"); -- fails
    LSOutput output = feature.createLSOutput();
    output.setByteStream(System.out);
    serializer.write(doc, output);
    */
    TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer transformer = transformerFactory.newTransformer();
    transformer.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING, "UTF-8");
    transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes");
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); // XXX portable?
    transformer.transform(new DOMSource(doc), new StreamResult(System.out));
  }
  public void writeTextElement(Element xmlParent, ResultSet rs, String value, String xmlTagName)
  {
    if ( ! hasValue(value))
      return;
    Element el = (Element) xmlParent.appendChild(xmlParent.getOwnerDocument().createElement(xmlTagName));
    el.appendChild(xmlParent.getOwnerDocument().createTextNode(value));
  }
  public boolean hasValue(String value)
  {
    return value != null && ! value.trim().isEmpty();
  }
  public static void main(String[] args) throws SQLException, Misconfiguration
  {
    try
    {
      new LineupExporter();
      System.exit(0);
    }
    catch (Exception e)
    {
      Util.error(e);
      System.exit(1);
    }
  }
}
