/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.tika.parser.iwork;

import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
import org.apache.tika.sax.XHTMLContentHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

class KeynoteContentHandler extends DefaultHandler {

    public final static String PRESENTATION_WIDTH = "slides-width";
    public final static String PRESENTATION_HEIGHT = "slides-height";

    private final XHTMLContentHandler xhtml;
    private final Metadata metadata;

    private boolean inSlide = false;
    private boolean inTheme = false;
    private boolean inTitle = false;
    private boolean inBody = false;
    private String tableId;
    private Integer numberOfColumns = null;
    private Integer currentColumn = null;

    private boolean inMetadata = false;
    private boolean inMetaDataTitle = false;
    private boolean inMetaDataAuthors = false;

    private boolean inParsableText = false;

    private int numberOfSlides = 0;

    KeynoteContentHandler(XHTMLContentHandler xhtml, Metadata metadata) {
        this.xhtml = xhtml;
        this.metadata = metadata;
    }

    @Override
    public void endDocument() throws SAXException {
        metadata.set(Metadata.SLIDE_COUNT, String.valueOf(numberOfSlides));
    }

    @Override
    public void startElement(
            String uri, String localName, String qName, Attributes attributes)
            throws SAXException {
        if ("key:theme".equals(qName)) {
            inTheme = true;
        } else if ("key:slide".equals(qName)) {
            inSlide = true;
            numberOfSlides++;
            xhtml.startElement("div");
        } else if ("key:master-slide".equals(qName)) {
            inSlide = true;
            xhtml.startElement("div");
        } else if ("key:title-placeholder".equals(qName) && inSlide) {
            inTitle = true;
            xhtml.startElement("h1");
        } else if ("sf:sticky-note".equals(qName) && inSlide) {
            xhtml.startElement("p");
        } else if ("key:notes".equals(qName) && inSlide) {
            xhtml.startElement("p");
        } else if ("key:body-placeholder".equals(qName) && inSlide) {
            xhtml.startElement("p");
            inBody = true;
        } else if ("key:size".equals(qName) && !inTheme) {
            String width = attributes.getValue("sfa:w");
            String height = attributes.getValue("sfa:h");
            metadata.set(PRESENTATION_WIDTH, width);
            metadata.set(PRESENTATION_HEIGHT, height);
        } else if ("sf:text-body".equals(qName)) {
            inParsableText = true;
        } else if ("key:metadata".equals(qName)) {
            inMetadata = true;
        } else if (inMetadata && "key:title".equals(qName)) {
            inMetaDataTitle = true;
        } else if (inMetadata && "key:authors".equals(qName)) {
            inMetaDataAuthors = true;
        } else if (inMetaDataTitle && "key:string".equals(qName)) {
            metadata.set(TikaCoreProperties.TITLE, attributes.getValue("sfa:string"));
        } else if (inMetaDataAuthors && "key:string".equals(qName)) {
            metadata.add(TikaCoreProperties.CREATOR, attributes.getValue("sfa:string"));
        } else if (inSlide && "sf:tabular-model".equals(qName)) {
            tableId = attributes.getValue("sfa:ID");
            xhtml.startElement("table");
        } else if (tableId != null && "sf:columns".equals(qName)) {
            numberOfColumns = Integer.parseInt(attributes.getValue("sf:count"));
            currentColumn = 0;
        } else if (tableId != null && "sf:ct".equals(qName)) {
            parseTableData(attributes.getValue("sfa:s"));
        } else if (tableId != null && "sf:n".equals(qName)) {
            parseTableData(attributes.getValue("sf:v"));
        } else if ("sf:p".equals(qName)) {
            xhtml.startElement("p");
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        if ("key:theme".equals(qName)) {
            inTheme = false;
        } else if ("key:slide".equals(qName)) {
            inSlide = false;
            xhtml.endElement("div");
        } else if ("key:master-slide".equals(qName)) {
            inSlide = false;
            xhtml.endElement("div");
        } else if ("key:title-placeholder".equals(qName) && inSlide) {
            inTitle = false;
            xhtml.endElement("h1");
        } else if ("sf:sticky-note".equals(qName) && inSlide) {
            xhtml.endElement("p");
        } else if ("key:notes".equals(qName) && inSlide) {
            xhtml.endElement("p");
        } else if ("key:body-placeholder".equals(qName) && inSlide) {
            xhtml.endElement("p");
            inBody = false;
        } else if ("sf:text-body".equals(qName)) {
            inParsableText = false;
        } else if ("key:metadata".equals(qName)) {
            inMetadata = false;
        } else if (inMetadata && "key:title".equals(qName)) {
            inMetaDataTitle = false;
        } else if (inMetadata && "key:authors".equals(qName)) {
            inMetaDataAuthors = false;
        } else if (inSlide && "sf:tabular-model".equals(qName)) {
            xhtml.endElement("table");
            tableId = null;
            numberOfColumns = null;
            currentColumn = null;
        } else if ("sf:p".equals(qName)) {
            xhtml.endElement("p");
        }
    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        if (inParsableText && inSlide && length != 0) {
            xhtml.characters(ch, start, length);
        }
    }

    private void parseTableData(String value) throws SAXException {
      if (currentColumn == 0) {
          xhtml.startElement("tr");
      }
      xhtml.element("td", value);

      currentColumn++;
      if (currentColumn.equals(numberOfColumns)) {
          xhtml.endElement("tr");
          currentColumn = 0;
      }
    }

}
