// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed 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 com.google.enterprise.adaptor.sharepoint;

import com.google.common.annotations.VisibleForTesting;

import com.microsoft.schemas.sharepoint.soap.ContentDatabase;
import com.microsoft.schemas.sharepoint.soap.Item;
import com.microsoft.schemas.sharepoint.soap.ItemData;
import com.microsoft.schemas.sharepoint.soap.ObjectType;
import com.microsoft.schemas.sharepoint.soap.SPContentDatabase;
import com.microsoft.schemas.sharepoint.soap.Site;
import com.microsoft.schemas.sharepoint.soap.SiteDataSoap;
import com.microsoft.schemas.sharepoint.soap.VirtualServer;
import com.microsoft.schemas.sharepoint.soap.Web;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.StringReader;
import java.util.logging.*;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.ws.Holder;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;

class SiteDataClient {
  /** SharePoint's namespace. */
  private static final String XMLNS
      = "http://schemas.microsoft.com/sharepoint/soap/";

  private static final Logger log
      = Logger.getLogger(SiteDataClient.class.getName());
  /**
   * The JAXBContext is expensive to initialize, so we share a copy between
   * instances.
   */
  private static final JAXBContext jaxbContext;
  /**
   * XML Schema of requests and responses. Used to validate responses match
   * expectations.
   */
  private static final Schema schema;

  static {
    try {
      jaxbContext = JAXBContext.newInstance(
          "com.microsoft.schemas.sharepoint.soap");
    } catch (JAXBException ex) {
      throw new RuntimeException("Could not initialize JAXBContext", ex);
    }

    try {
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      dbf.setNamespaceAware(true);
      Document doc = dbf.newDocumentBuilder()
          .parse(SiteDataSoap.class.getResourceAsStream("SiteData.wsdl"));
      String schemaNs = XMLConstants.W3C_XML_SCHEMA_NS_URI;
      Node schemaNode = doc.getElementsByTagNameNS(schemaNs, "schema").item(0);
      schema = SchemaFactory.newInstance(schemaNs).newSchema(
          new DOMSource(schemaNode));
    } catch (IOException ex) {
      throw new RuntimeException("Could not initialize Schema", ex);
    } catch (SAXException ex) {
      throw new RuntimeException("Could not initialize Schema", ex);
    } catch (ParserConfigurationException ex) {
      throw new RuntimeException("Could not initialize Schema", ex);
    }
  }

  private final CheckedExceptionSiteDataSoap siteData;
  private final boolean xmlValidation;

  public SiteDataClient(SiteDataSoap siteDataSoap, boolean xmlValidation) {
    if (siteDataSoap == null) {
      throw new NullPointerException();
    }
    siteDataSoap = LoggingWSHandler.create(SiteDataSoap.class, siteDataSoap);
    this.siteData = new CheckedExceptionSiteDataSoapAdapter(siteDataSoap);
    this.xmlValidation = xmlValidation;
  }

  public long getSiteAndWeb(String strUrl, Holder<String> strSite,
      Holder<String> strWeb) throws IOException {
    Holder<Long> getSiteAndWebResult = new Holder<Long>();
    siteData.getSiteAndWeb(strUrl, getSiteAndWebResult, strSite, strWeb);
    return getSiteAndWebResult.value;
  }

  public boolean getUrlSegments(String strURL, Holder<String> strListID,
      Holder<String> strItemID) throws IOException {
    Holder<Boolean> getURLSegmentsResult = new Holder<Boolean>();
    // The returned web is not useful because we already know the web containing
    // the URL. We don't have a use for the returned bucket.
    siteData.getURLSegments(strURL, getURLSegmentsResult, null, null,
        strListID, strItemID);
    return getURLSegmentsResult.value;
  }

  public VirtualServer getContentVirtualServer() throws IOException {
    log.entering("SiteDataClient", "getContentVirtualServer");
    Holder<String> result = new Holder<String>();
    siteData.getContent(ObjectType.VIRTUAL_SERVER, null, null, null, true,
        false, null, result);
    String xml = result.value;
    xml = xml.replace("<VirtualServer>",
        "<VirtualServer xmlns='" + XMLNS + "'>");
    VirtualServer vs = jaxbParse(xml, VirtualServer.class);
    log.exiting("SiteDataClient", "getContentVirtualServer", vs);
    return vs;
  }

  public ContentDatabase getContentContentDatabase(String id,
      boolean retrieveChildItems) throws IOException {
    log.entering("SiteDataClient", "getContentContentDatabase", id);
    Holder<String> result = new Holder<String>();
    siteData.getContent(ObjectType.CONTENT_DATABASE, id, null, null,
        retrieveChildItems, false, null, result);
    String xml = result.value;
    xml = xml.replace("<ContentDatabase>",
        "<ContentDatabase xmlns='" + XMLNS + "'>");
    ContentDatabase cd = jaxbParse(xml, ContentDatabase.class);
    log.exiting("SiteDataClient", "getContentContentDatabase", cd);
    return cd;
  }

  public Site getContentSite() throws IOException {
    log.entering("SiteDataClient", "getContentSite");
    Holder<String> result = new Holder<String>();
    final boolean retrieveChildItems = true;
    // When ObjectType is SITE_COLLECTION, retrieveChildItems is the only
    // input value consulted.
    siteData.getContent(ObjectType.SITE_COLLECTION, null, null, null,
        retrieveChildItems, false, null, result);
    String xml = result.value;
    xml = xml.replace("<Site>", "<Site xmlns='" + XMLNS + "'>");
    Site site = jaxbParse(xml, Site.class);
    log.exiting("SiteDataClient", "getContentSite", site);
    return site;
  }

  public Web getContentWeb() throws IOException {
    log.entering("SiteDataClient", "getContentWeb");
    Holder<String> result = new Holder<String>();
    siteData.getContent(ObjectType.SITE, null, null, null, true, false, null,
        result);
    String xml = result.value;
    xml = xml.replace("<Web>", "<Web xmlns='" + XMLNS + "'>");
    Web web = jaxbParse(xml, Web.class);
    log.exiting("SiteDataClient", "getContentWeb", web);
    return web;
  }

  public com.microsoft.schemas.sharepoint.soap.List getContentList(String id)
      throws IOException {
    log.entering("SiteDataClient", "getContentList", id);
    Holder<String> result = new Holder<String>();
    siteData.getContent(ObjectType.LIST, id, null, null, false, false, null,
        result);
    String xml = result.value;
    xml = xml.replace("<List>", "<List xmlns='" + XMLNS + "'>");
    com.microsoft.schemas.sharepoint.soap.List list = jaxbParse(xml,
        com.microsoft.schemas.sharepoint.soap.List.class);
    log.exiting("SiteDataClient", "getContentList", list);
    return list;
  }

  public ItemData getContentItem(String listId, String itemId)
      throws IOException {
    log.entering("SiteDataClient", "getContentItem",
        new Object[] {listId, itemId});
    Holder<String> result = new Holder<String>();
    siteData.getContent(ObjectType.LIST_ITEM, listId, "", itemId, false,
        false, null, result);
    String xml = result.value;
    xml = xml.replace("<Item>", "<ItemData xmlns='" + XMLNS + "'>");
    xml = xml.replace("</Item>", "</ItemData>");
    ItemData data = jaxbParse(xml, ItemData.class);
    log.exiting("SiteDataClient", "getContentItem", data);
    return data;
  }

  public Paginator<ItemData> getContentFolderChildren(final String guid,
      final String url) {
    log.entering("SiteDataClient", "getContentFolderChildren",
        new Object[] {guid, url});
    final Holder<String> lastItemIdOnPage = new Holder<String>("");
    log.exiting("SiteDataClient", "getContentFolderChildren");
    return new Paginator<ItemData>() {
      @Override
      public ItemData next() throws IOException {
        if (lastItemIdOnPage.value == null) {
          return null;
        }
        Holder<String> result = new Holder<String>();
        siteData.getContent(ObjectType.FOLDER, guid, url, null, true, false,
            lastItemIdOnPage, result);
        String xml = result.value;
        xml = xml.replace("<Folder>", "<Folder xmlns='" + XMLNS + "'>");
        return jaxbParse(xml, ItemData.class);
      }
    };
  }

  public Item getContentListItemAttachments(String listId, String itemId)
      throws IOException {
    log.entering("SiteDataClient", "getContentListItemAttachments",
        new Object[] {listId, itemId});
    Holder<String> result = new Holder<String>();
    siteData.getContent(ObjectType.LIST_ITEM_ATTACHMENTS, listId, "",
        itemId, true, false, null, result);
    String xml = result.value;
    xml = xml.replace("<Item ", "<Item xmlns='" + XMLNS + "' ");
    Item item = jaxbParse(xml, Item.class);
    log.exiting("SiteDataClient", "getContentListItemAttachments", item);
    return item;
  }

  /**
   * Get a paginator that allows looping over all the changes since {@code
   * startChangeId}. If next() throws an XmlProcessingException, it is
   * guaranteed to be after state has been updated so that a subsequent call
   * to next() will provide the next page and not repeat the erroring page.
   */
  public CursorPaginator<SPContentDatabase, String>
      getChangesContentDatabase(final String contentDatabaseGuid,
          String startChangeId, final boolean isSp2010) {
    log.entering("SiteDataClient", "getChangesContentDatabase",
        new Object[] {contentDatabaseGuid, startChangeId});
    final Holder<String> lastChangeId = new Holder<String>(startChangeId);
    final Holder<String> lastLastChangeId = new Holder<String>();
    final Holder<String> currentChangeId = new Holder<String>();
    final Holder<Boolean> moreChanges = new Holder<Boolean>(true);
    log.exiting("SiteDataClient", "getChangesContentDatabase");
    return new CursorPaginator<SPContentDatabase, String>() {
      @Override
      public SPContentDatabase next() throws IOException {
        if (!moreChanges.value) {
          return null;
        }
        lastLastChangeId.value = lastChangeId.value;
        Holder<String> result = new Holder<String>();
        // In non-SP2010, the timeout is a number of seconds. In SP2010, the
        // timeout is n * 60, where n is the number of items you want
        // returned. However, in SP2010, asking for more than 10 items seems
        // to lose results. If timeout is less than 60 in SP 2010, then it
        // causes an infinite loop.
        int timeout = isSp2010 ? 10 * 60 : 15;
        siteData.getChanges(ObjectType.CONTENT_DATABASE, contentDatabaseGuid,
            lastChangeId, currentChangeId, timeout, result, moreChanges);
        // XmlProcessingExceptions fine after this point.
        String xml = result.value;
        xml = xml.replace("<SPContentDatabase ",
            "<SPContentDatabase xmlns='" + XMLNS + "' ");
        return jaxbParse(xml, SPContentDatabase.class);
      }

      @Override
      public String getCursor() {
        return lastChangeId.value;
      }
    };
  }

  @VisibleForTesting
  <T> T jaxbParse(String xml, Class<T> klass)
      throws XmlProcessingException {
    Source source = new StreamSource(new StringReader(xml));
    try {
      Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
      if (xmlValidation) {
        unmarshaller.setSchema(schema);
      }
      return unmarshaller.unmarshal(source, klass).getValue();
    } catch (JAXBException ex) {
      throw new XmlProcessingException(ex, xml);
    }
  }

  /**
   * Container exception for wrapping xml processing exceptions in IOExceptions.
   */
  public static class XmlProcessingException extends IOException {
    public XmlProcessingException(JAXBException cause, String xml) {
      super("Error when parsing xml: " + xml, cause);
    }
  }

  /**
   * Container exception for wrapping WebServiceExceptions in a checked
   * exception.
   */
  public static class WebServiceIOException extends IOException {
    public WebServiceIOException(WebServiceException cause) {
      super(cause);
    }
  }

  /**
   * An object that can be paged through.
   *
   * @param <E> element type returned by {@link #next}
   */
  public interface Paginator<E> {
    /**
     * Get the next page of the series. If an exception is thrown, the state of
     * the paginator is undefined.
     *
     * @return the next page of data, or {@code null} if no more pages available
     */
    public E next() throws IOException;
  }

  /**
   * An object that can be paged through, but also provide a cursor for learning
   * its current position.
   *
   * @param <E> element type returned by {@link #next}
   * @param <C> cursor type
   */
  public interface CursorPaginator<E, C> extends Paginator<E> {
    /**
     * Provides a cursor for the current position. The intent is that you could
     * get a cursor (even in the event of {@link #next} throwing an exception)
     * and use it to create a query that would continue without repeating
     * results.
     */
    public C getCursor();
  }

  public static Service createSiteDataService() {
    return Service.create(
        SiteDataSoap.class.getResource("SiteData.wsdl"),
        new QName(XMLNS, "SiteData"));
  }

  /**
   * A subset of SiteDataSoap that throws WebServiceIOExceptions instead of the
   * WebServiceException (which is a RuntimeException).
   */
  private static interface CheckedExceptionSiteDataSoap {
    public void getSiteAndWeb(String strUrl, Holder<Long> getSiteAndWebResult,
        Holder<String> strSite, Holder<String> strWeb)
        throws WebServiceIOException;

    public void getURLSegments(String strURL,
        Holder<Boolean> getURLSegmentsResult, Holder<String> strWebID,
        Holder<String> strBucketID, Holder<String> strListID,
        Holder<String> strItemID) throws WebServiceIOException;

    public void getContent(ObjectType objectType, String objectId,
        String folderUrl, String itemId, boolean retrieveChildItems,
        boolean securityOnly, Holder<String> lastItemIdOnPage,
        Holder<String> getContentResult) throws WebServiceIOException;

    public void getChanges(ObjectType objectType, String contentDatabaseId,
        Holder<String> lastChangeId, Holder<String> currentChangeId,
        Integer timeout, Holder<String> getChangesResult,
        Holder<Boolean> moreChanges) throws WebServiceIOException;
  }

  private static class CheckedExceptionSiteDataSoapAdapter
      implements CheckedExceptionSiteDataSoap {
    private final SiteDataSoap siteData;

    public CheckedExceptionSiteDataSoapAdapter(SiteDataSoap siteData) {
      this.siteData = siteData;
    }

    @Override
    public void getSiteAndWeb(String strUrl, Holder<Long> getSiteAndWebResult,
        Holder<String> strSite, Holder<String> strWeb)
        throws WebServiceIOException {
      try {
        siteData.getSiteAndWeb(strUrl, getSiteAndWebResult, strSite, strWeb);
      } catch (WebServiceException ex) {
        throw new WebServiceIOException(ex);
      }
    }

    @Override
    public void getURLSegments(String strURL,
        Holder<Boolean> getURLSegmentsResult, Holder<String> strWebID,
        Holder<String> strBucketID, Holder<String> strListID,
        Holder<String> strItemID) throws WebServiceIOException {
      try {
        siteData.getURLSegments(strURL, getURLSegmentsResult, strWebID,
            strBucketID, strListID, strItemID);
      } catch (WebServiceException ex) {
        throw new WebServiceIOException(ex);
      }
    }

    @Override
    public void getContent(ObjectType objectType, String objectId,
        String folderUrl, String itemId, boolean retrieveChildItems,
        boolean securityOnly, Holder<String> lastItemIdOnPage,
        Holder<String> getContentResult) throws WebServiceIOException {
      try {
        siteData.getContent(objectType, objectId, folderUrl, itemId,
            retrieveChildItems, securityOnly, lastItemIdOnPage,
            getContentResult);
      } catch (WebServiceException ex) {
        throw new WebServiceIOException(ex);
      }
    }

    @Override
    public void getChanges(ObjectType objectType, String contentDatabaseId,
        Holder<String> lastChangeId, Holder<String> currentChangeId,
        Integer timeout, Holder<String> getChangesResult,
        Holder<Boolean> moreChanges) throws WebServiceIOException {
      try {
        siteData.getChanges(objectType, contentDatabaseId, lastChangeId,
            currentChangeId, timeout, getChangesResult, moreChanges);
      } catch (WebServiceException ex) {
        throw new WebServiceIOException(ex);
      }
    }
  }
}
