package org.bucksch.zeipis.importer;
import org.bucksch.zeipis.all.*;
import org.w3c.dom.*;
import java.io.InputStream;
import java.net.URL;
import java.sql.*;
import javax.xml.parsers.DocumentBuilderFactory;

public class LineupImporter
{
  protected PreparedStatement findChannelByDVBID;
  protected PreparedStatement findChannelByDVBName;
  protected PreparedStatement updateStationXMLTVID;
  protected PreparedStatement updateStationName;
  protected PreparedStatement updateStationPreset;
  protected PreparedStatement updateStationLogo;
  protected PreparedStatement updateStationCommFree;
  protected PreparedStatement updateStationGroup;
  protected void createSQLStatements()
    throws SQLException
  {
    Connection db = DB.me.database();
    findChannelByDVBID = db.prepareStatement("SELECT * FROM channel LEFT JOIN dvb_transponder USING (dvb_transponderid) WHERE dvb_serviceid = ? AND transportid = ? AND networkid = ?");
    findChannelByDVBName = db.prepareStatement("SELECT * FROM channel WHERE tech_name = ?");
    updateStationXMLTVID = db.prepareStatement("UPDATE station SET xmltvid = ? WHERE stationid = ? AND auto is not false");
    final String suffix = " WHERE xmltvid = ? AND auto is not false";
    updateStationName = db.prepareStatement("UPDATE station SET long_name = ?, short_name = ?" + suffix);
    updateStationLogo = db.prepareStatement("UPDATE station SET icon = ?" + suffix);
    updateStationPreset = db.prepareStatement("UPDATE station SET preset = ?" + suffix);
    updateStationCommFree = db.prepareStatement("UPDATE station SET commercial_free = ?" + suffix);
    updateStationGroup = db.prepareStatement("UPDATE station SET station_group = ?" + suffix);
  }
  public LineupImporter()
    throws Exception
  {
    // Init DB and create XML DOM
    new CoreData();
    createSQLStatements();

    InputStream fetcher = new URL("http://www.bucksch.org/1/projects/various/xmltv/lineup.de.xml").openStream(); // TODO select URL and display progress
    Util.debug("fetching and parsing...");
    Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(fetcher);
    Util.debug("done.");

    NodeList stations = doc.getElementsByTagName("station");
    NodeList dvbchannels = doc.getElementsByTagName("dvb-channel");
    for (int i = 0; i < stations.getLength(); i++)
      parseDVBChannel((Element) dvbchannels.item(i));
    for (int i = 0; i < stations.getLength(); i++)
      parseStation((Element) stations.item(i));
  }
  public void parseDVBChannel(Element channel)
  {
    try {
      // Read <dvb-channel> XML
      String xmltvID = channel.getAttribute("rfc2838id");
      Element dvbid = (Element) channel.getElementsByTagName("dvb-id").item(0);
      int serviceID = Integer.parseInt(dvbid.getAttribute("service"));
      int transportID = Integer.parseInt(dvbid.getAttribute("transport"));
      int networkID = Integer.parseInt(dvbid.getAttribute("network"));
      Element dvbname = (Element) channel.getElementsByTagName("dvb-name").item(0);
      String serviceName = dvbname.getAttribute("service");
      //String providerName = dvbname.getAttribute("provider");

      // Find channel -> station in DB
      int dbStationID = -1;
      findChannelByDVBID.clearBatch();
      findChannelByDVBID.setInt(1, serviceID);
      findChannelByDVBID.setInt(2, transportID);
      findChannelByDVBID.setInt(3, networkID);
      ResultSet rs = findChannelByDVBID.executeQuery();
      if (rs.first())
      {
        dbStationID = rs.getInt("stationid");
      }
      else
      {
        findChannelByDVBName.clearBatch();
        findChannelByDVBName.setString(1, serviceName);
        //findChannelByName.setString(2, providerName);
        rs = findChannelByDVBName.executeQuery();
        if (rs.first())
        {
          dbStationID = rs.getInt("stationid");
        }
        else
        {
          // channel not in DB, so can't be received anyways
          return;
        }
      }
      
      // Update XMLTVID for station
      updateStationXMLTVID.clearBatch();
      updateStationXMLTVID.setString(1, xmltvID);
      updateStationXMLTVID.setInt(2, dbStationID);
      int count = updateStationXMLTVID.executeUpdate();
      if (count == 1)
        Util.debug("Station ID " + xmltvID + " updated");

    } catch (Exception e) { Util.error(e); }
  }
  public void parseStation(Element station)
  {
    try {
      // Read <station> XML
      String xmltvID = station.getAttribute("rfc2838id");
      String longName = readElementText(station, "long-name");
      String shortName = readElementText(station, "short-name");
      if (longName == null || shortName == null || longName.trim().isEmpty() || shortName.trim().isEmpty())
        throw new Exception("station long/short name missing");
      Element logoE = (Element) station.getElementsByTagName("logo").item(0);
      String logoURL = logoE != null ? logoE.getAttribute("url") : null;
      int preset = 0;
      String presetStr = readElementText(station, "preset");
      if (presetStr != null)
        preset = Integer.parseInt(presetStr);
      String commFreeStr = readElementText(station, "commercial-free");
      String group = readElementText(station, "group");

      // Update station - if it is in DB with this XMLTVID
      updateStationName.clearBatch();
      updateStationName.setString(1, longName);
      updateStationName.setString(2, shortName);
      updateStationName.setString(3, xmltvID);
      int count = updateStationName.executeUpdate();
      if (count == 1)
        Util.debug("Station " + xmltvID + " updated name: " + longName + " / " + shortName);

      if (preset != 0)
      {
        updateStationPreset.clearBatch();
        updateStationPreset.setInt(1, preset);
        updateStationPreset.setString(2, xmltvID);
        count = updateStationPreset.executeUpdate();
        if (count == 1)
          Util.debug("Station " + xmltvID + " updated preset: " + preset);
      }

      if (logoURL != null)
      {
        updateStationLogo.clearBatch();
        updateStationLogo.setString(1, logoURL);
        updateStationLogo.setString(2, xmltvID);
        count = updateStationLogo.executeUpdate();
        if (count == 1)
          Util.debug("Station " + xmltvID + " updated logo: " + logoURL);
      }
      
      if (commFreeStr != null)
      {
        updateStationCommFree.clearBatch();
        updateStationCommFree.setBoolean(1, Boolean.parseBoolean(commFreeStr));
        updateStationCommFree.setString(2, xmltvID);
        count = updateStationCommFree.executeUpdate();
        if (count == 1)
          Util.debug("Station " + xmltvID + " updated commercial free: " + commFreeStr);
      }
      
      if (group != null)
      {
        updateStationGroup.clearBatch();
        updateStationGroup.setString(1, group);
        updateStationGroup.setString(2, xmltvID);
        count = updateStationGroup.executeUpdate();
        if (count == 1)
          Util.debug("Station " + xmltvID + " updated group: " + group);
      }

    } catch (Exception e) { Util.error(e); }
  }
  public String readElementText(Element xmlParent, String elementName)
  {
    NodeList list = xmlParent.getElementsByTagName(elementName);
    if (list.getLength() == 0)
      return null;
    return list.item(0).getFirstChild().getNodeValue();
  }
  public static void main(String[] args) throws SQLException, Misconfiguration
  {
    try
    {
      new LineupImporter();
      System.exit(0);
    }
    catch (Exception e)
    {
      Util.error(e);
      System.exit(1);
    }
  }
}
