/*
 * 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.chemistry.opencmis.client.runtime;

import static org.apache.chemistry.opencmis.commons.impl.CollectionsHelper.isNullOrEmpty;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.client.api.Document;
import org.apache.chemistry.opencmis.client.api.DocumentType;
import org.apache.chemistry.opencmis.client.api.ObjectFactory;
import org.apache.chemistry.opencmis.client.api.ObjectId;
import org.apache.chemistry.opencmis.client.api.ObjectType;
import org.apache.chemistry.opencmis.client.api.OperationContext;
import org.apache.chemistry.opencmis.client.api.Policy;
import org.apache.chemistry.opencmis.client.api.Property;
import org.apache.chemistry.opencmis.client.bindings.spi.LinkAccess;
import org.apache.chemistry.opencmis.client.runtime.util.AppendOutputStream;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.Ace;
import org.apache.chemistry.opencmis.commons.data.ContentStream;
import org.apache.chemistry.opencmis.commons.data.ContentStreamHash;
import org.apache.chemistry.opencmis.commons.data.ObjectData;
import org.apache.chemistry.opencmis.commons.data.PartialContentStream;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
import org.apache.chemistry.opencmis.commons.enums.Updatability;
import org.apache.chemistry.opencmis.commons.enums.VersioningState;
import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamHashImpl;
import org.apache.chemistry.opencmis.commons.spi.Holder;

public class DocumentImpl extends AbstractFilableCmisObject implements Document {

    private static final long serialVersionUID = 1L;

    /**
     * Constructor.
     */
    public DocumentImpl(SessionImpl session, ObjectType objectType, ObjectData objectData, OperationContext context) {
        initialize(session, objectType, objectData, context);
    }

    @Override
    public DocumentType getDocumentType() {
        ObjectType objectType = super.getType();
        if (objectType instanceof DocumentType) {
            return (DocumentType) objectType;
        } else {
            throw new ClassCastException("Object type is not a document type.");
        }
    }

    @Override
    public boolean isVersionable() {
        return Boolean.TRUE.equals(getDocumentType().isVersionable());
    }

    // properties

    @Override
    public String getCheckinComment() {
        return getPropertyValue(PropertyIds.CHECKIN_COMMENT);
    }

    @Override
    public String getVersionLabel() {
        return getPropertyValue(PropertyIds.VERSION_LABEL);
    }

    @Override
    public String getVersionSeriesId() {
        return getPropertyValue(PropertyIds.VERSION_SERIES_ID);
    }

    @Override
    public String getVersionSeriesCheckedOutId() {
        return getPropertyValue(PropertyIds.VERSION_SERIES_CHECKED_OUT_ID);
    }

    @Override
    public String getVersionSeriesCheckedOutBy() {
        return getPropertyValue(PropertyIds.VERSION_SERIES_CHECKED_OUT_BY);
    }

    @Override
    public Boolean isImmutable() {
        return getPropertyValue(PropertyIds.IS_IMMUTABLE);
    }

    @Override
    public Boolean isLatestMajorVersion() {
        return getPropertyValue(PropertyIds.IS_LATEST_MAJOR_VERSION);
    }

    @Override
    public Boolean isLatestVersion() {
        return getPropertyValue(PropertyIds.IS_LATEST_VERSION);
    }

    @Override
    public Boolean isMajorVersion() {
        return getPropertyValue(PropertyIds.IS_MAJOR_VERSION);
    }

    @Override
    public Boolean isPrivateWorkingCopy() {
        return getPropertyValue(PropertyIds.IS_PRIVATE_WORKING_COPY);
    }

    @Override
    public Boolean isVersionSeriesCheckedOut() {
        return getPropertyValue(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT);
    }

    @Override
    public long getContentStreamLength() {
        BigInteger bigInt = getPropertyValue(PropertyIds.CONTENT_STREAM_LENGTH);
        return bigInt == null ? (long) -1 : bigInt.longValue();
    }

    @Override
    public String getContentStreamMimeType() {
        return getPropertyValue(PropertyIds.CONTENT_STREAM_MIME_TYPE);
    }

    @Override
    public String getContentStreamFileName() {
        return getPropertyValue(PropertyIds.CONTENT_STREAM_FILE_NAME);
    }

    @Override
    public String getContentStreamId() {
        return getPropertyValue(PropertyIds.CONTENT_STREAM_ID);
    }

    @Override
    public List<ContentStreamHash> getContentStreamHashes() {
        List<String> hashes = getPropertyValue(PropertyIds.CONTENT_STREAM_HASH);
        if (isNullOrEmpty(hashes)) {
            return null;
        }

        List<ContentStreamHash> result = new ArrayList<ContentStreamHash>(hashes.size());
        for (String hash : hashes) {
            result.add(new ContentStreamHashImpl(hash));
        }

        return result;
    }

    @Override
    public String getLatestAccessibleStateId() {
        return getPropertyValue(PropertyIds.LATEST_ACCESSIBLE_STATE_ID);
    }

    // operations

    @Override
    public Document copy(ObjectId targetFolderId, Map<String, ?> properties, VersioningState versioningState,
            List<Policy> policies, List<Ace> addAces, List<Ace> removeAces, OperationContext context) {

        ObjectId newId = null;
        try {
            newId = getSession().createDocumentFromSource(this, properties, targetFolderId, versioningState, policies,
                    addAces, removeAces);
        } catch (CmisNotSupportedException nse) {
            newId = copyViaClient(targetFolderId, properties, versioningState, policies, addAces, removeAces);
        }

        // if no context is provided the object will not be fetched
        if (context == null || newId == null) {
            return null;
        }
        // get the new object
        CmisObject object = getSession().getObject(newId, context);
        if (!(object instanceof Document)) {
            throw new CmisRuntimeException("Newly created object is not a document! New id: " + newId);
        }

        return (Document) object;
    }

    @Override
    public Document copy(ObjectId targetFolderId) {
        return copy(targetFolderId, null, null, null, null, null, getSession().getDefaultContext());
    }

    /**
     * Copies the document manually. The content is streamed from the repository
     * and back.
     */
    protected ObjectId copyViaClient(ObjectId targetFolderId, Map<String, ?> properties,
            VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces) {
        Map<String, Object> newProperties = new HashMap<String, Object>();

        OperationContext allPropsContext = getSession().createOperationContext();
        allPropsContext.setFilterString("*");
        allPropsContext.setIncludeAcls(false);
        allPropsContext.setIncludeAllowableActions(false);
        allPropsContext.setIncludePathSegments(false);
        allPropsContext.setIncludePolicies(false);
        allPropsContext.setIncludeRelationships(IncludeRelationships.NONE);
        allPropsContext.setRenditionFilterString("cmis:none");

        Document allPropsDoc = (Document) getSession().getObject(this, allPropsContext);

        for (Property<?> prop : allPropsDoc.getProperties()) {
            if (prop.getDefinition().getUpdatability() == Updatability.READWRITE
                    || prop.getDefinition().getUpdatability() == Updatability.ONCREATE) {
                newProperties.put(prop.getId(), prop.getValue());
            }
        }

        if (properties != null) {
            newProperties.putAll(properties);
        }

        ContentStream contentStream = allPropsDoc.getContentStream();
        try {
            return getSession().createDocument(newProperties, targetFolderId, contentStream, versioningState, policies,
                    addAces, removeAces);
        } finally {
            if (contentStream != null) {
                InputStream stream = contentStream.getStream();
                if (stream != null) {
                    try {
                        stream.close();
                    } catch (IOException ioe) {
                        throw new CmisRuntimeException("Cannot close source stream!", ioe);
                    }
                }
            }
        }
    }

    @Override
    public void deleteAllVersions() {
        delete(true);
    }

    // versioning

    @Override
    public ObjectId checkOut() {
        String newObjectId = null;

        readLock();
        try {
            String objectId = getObjectId();
            Holder<String> objectIdHolder = new Holder<String>(objectId);

            getBinding().getVersioningService().checkOut(getRepositoryId(), objectIdHolder, null, null);
            newObjectId = objectIdHolder.getValue();
        } finally {
            readUnlock();
        }

        // remove original version from cache, the path and a few versioning
        // properties are not valid anymore
        getSession().removeObjectFromCache(this);

        if (newObjectId == null) {
            return null;
        }

        return getSession().createObjectId(newObjectId);
    }

    @Override
    public void cancelCheckOut() {
        String objectId = getObjectId();

        getBinding().getVersioningService().cancelCheckOut(getRepositoryId(), objectId, null);

        // remove PWC from cache, it doesn't exist anymore
        getSession().removeObjectFromCache(this);
    }

    @Override
    public ObjectId checkIn(boolean major, Map<String, ?> properties, ContentStream contentStream,
            String checkinComment, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces) {
        String newObjectId = null;

        readLock();
        try {
            Holder<String> objectIdHolder = new Holder<String>(getObjectId());

            ObjectFactory of = getObjectFactory();

            Set<Updatability> updatebility = EnumSet.noneOf(Updatability.class);
            updatebility.add(Updatability.READWRITE);
            updatebility.add(Updatability.WHENCHECKEDOUT);

            getBinding().getVersioningService().checkIn(getRepositoryId(), objectIdHolder, major,
                    of.convertProperties(properties, getType(), getSecondaryTypes(), updatebility),
                    of.convertContentStream(contentStream), checkinComment, of.convertPolicies(policies),
                    of.convertAces(addAces), of.convertAces(removeAces), null);

            newObjectId = objectIdHolder.getValue();
        } finally {
            readUnlock();
        }

        // remove PWC from cache, it doesn't exist anymore
        getSession().removeObjectFromCache(this);

        if (newObjectId == null) {
            return null;
        }

        return getSession().createObjectId(newObjectId);
    }

    @Override
    public List<Document> getAllVersions() {
        return getAllVersions(getSession().getDefaultContext());
    }

    @Override
    public List<Document> getAllVersions(OperationContext context) {
        String objectId;
        String versionSeriesId;

        readLock();
        try {
            objectId = getObjectId();
            versionSeriesId = getVersionSeriesId();
        } finally {
            readUnlock();
        }

        List<ObjectData> versions = getBinding().getVersioningService().getAllVersions(getRepositoryId(), objectId,
                versionSeriesId, context.getFilterString(), context.isIncludeAllowableActions(), null);

        ObjectFactory objectFactory = getSession().getObjectFactory();

        List<Document> result = new ArrayList<Document>();
        if (versions != null) {
            for (ObjectData objectData : versions) {
                CmisObject doc = objectFactory.convertObject(objectData, context);
                if (!(doc instanceof Document)) {
                    // should not happen...
                    continue;
                }

                result.add((Document) doc);
            }
        }

        return result;

    }

    @Override
    public Document getObjectOfLatestVersion(boolean major) {
        return getObjectOfLatestVersion(major, getSession().getDefaultContext());
    }

    @Override
    public Document getObjectOfLatestVersion(boolean major, OperationContext context) {
        return getSession().getLatestDocumentVersion(this, major, context);
    }

    // content operations

    @Override
    public ContentStream getContentStream() {
        return getContentStream(null, null, null);
    }

    @Override
    public ContentStream getContentStream(BigInteger offset, BigInteger length) {
        return getContentStream(null, offset, length);
    }

    @Override
    public ContentStream getContentStream(String streamId) {
        return getContentStream(streamId, null, null);
    }

    @Override
    public ContentStream getContentStream(String streamId, BigInteger offset, BigInteger length) {
        // get the stream
        ContentStream contentStream = getSession().getContentStream(this, streamId, offset, length);

        if (contentStream == null) {
            return null;
        }

        // the AtomPub binding doesn't return a file name
        // -> get the file name from properties, if present
        String filename = contentStream.getFileName();
        if (filename == null) {
            filename = getContentStreamFileName();
        }

        long lengthLong = (contentStream.getBigLength() == null ? -1 : contentStream.getBigLength().longValue());

        // convert and return stream object
        return getSession().getObjectFactory().createContentStream(filename, lengthLong, contentStream.getMimeType(),
                contentStream.getStream(), contentStream instanceof PartialContentStream);
    }

    @Override
    public String getContentUrl() {
        return getContentUrl(null);
    }

    @Override
    public String getContentUrl(String streamId) {
        if (getBinding().getObjectService() instanceof LinkAccess) {
            LinkAccess linkAccess = (LinkAccess) getBinding().getObjectService();

            if (streamId == null) {
                return linkAccess.loadContentLink(getRepositoryId(), getId());
            } else {
                return linkAccess.loadRenditionContentLink(getRepositoryId(), getId(), streamId);
            }
        }

        return null;
    }

    @Override
    public Document setContentStream(ContentStream contentStream, boolean overwrite) {
        ObjectId objectId = setContentStream(contentStream, overwrite, true);
        if (objectId == null) {
            return null;
        }

        if (!getObjectId().equals(objectId.getId())) {
            return (Document) getSession().getObject(objectId, getCreationContext());
        }

        return this;
    }

    @Override
    public ObjectId setContentStream(ContentStream contentStream, boolean overwrite, boolean refresh) {
        String newObjectId = null;

        readLock();
        try {
            Holder<String> objectIdHolder = new Holder<String>(getObjectId());
            Holder<String> changeTokenHolder = new Holder<String>((String) getPropertyValue(PropertyIds.CHANGE_TOKEN));

            getBinding().getObjectService().setContentStream(getRepositoryId(), objectIdHolder, overwrite,
                    changeTokenHolder, getObjectFactory().convertContentStream(contentStream), null);

            newObjectId = objectIdHolder.getValue();
        } finally {
            readUnlock();
        }

        if (refresh) {
            refresh();
        }

        if (newObjectId == null) {
            return null;
        }

        return getSession().createObjectId(newObjectId);
    }

    @Override
    public Document appendContentStream(ContentStream contentStream, boolean isLastChunk) {
        if (getSession().getRepositoryInfo().getCmisVersion() == CmisVersion.CMIS_1_0) {
            throw new CmisNotSupportedException("This method is not supported for CMIS 1.0 repositories.");
        }

        ObjectId objectId = appendContentStream(contentStream, isLastChunk, true);
        if (objectId == null) {
            return null;
        }

        if (!getObjectId().equals(objectId.getId())) {
            return (Document) getSession().getObject(objectId, getCreationContext());
        }

        return this;
    }

    @Override
    public ObjectId appendContentStream(ContentStream contentStream, boolean isLastChunk, boolean refresh) {
        if (getSession().getRepositoryInfo().getCmisVersion() == CmisVersion.CMIS_1_0) {
            throw new CmisNotSupportedException("This method is not supported for CMIS 1.0 repositories.");
        }

        String newObjectId = null;

        readLock();
        try {
            Holder<String> objectIdHolder = new Holder<String>(getObjectId());
            Holder<String> changeTokenHolder = new Holder<String>((String) getPropertyValue(PropertyIds.CHANGE_TOKEN));

            getBinding().getObjectService().appendContentStream(getRepositoryId(), objectIdHolder, changeTokenHolder,
                    getObjectFactory().convertContentStream(contentStream), isLastChunk, null);

            newObjectId = objectIdHolder.getValue();
        } finally {
            readUnlock();
        }

        if (refresh) {
            refresh();
        }

        if (newObjectId == null) {
            return null;
        }

        return getSession().createObjectId(newObjectId);
    }

    @Override
    public Document deleteContentStream() {
        ObjectId objectId = deleteContentStream(true);
        if (objectId == null) {
            return null;
        }

        if (!getObjectId().equals(objectId.getId())) {
            return (Document) getSession().getObject(objectId, getCreationContext());
        }

        return this;
    }

    @Override
    public ObjectId deleteContentStream(boolean refresh) {
        String newObjectId = null;

        readLock();
        try {
            Holder<String> objectIdHolder = new Holder<String>(getObjectId());
            Holder<String> changeTokenHolder = new Holder<String>((String) getPropertyValue(PropertyIds.CHANGE_TOKEN));

            getBinding().getObjectService().deleteContentStream(getRepositoryId(), objectIdHolder, changeTokenHolder,
                    null);

            newObjectId = objectIdHolder.getValue();
        } finally {
            readUnlock();
        }

        if (refresh) {
            refresh();
        }

        if (newObjectId == null) {
            return null;
        }

        return getSession().createObjectId(newObjectId);
    }

    @Override
    public OutputStream createOverwriteOutputStream(String filename, String mimeType) {
        if (getSession().getRepositoryInfo().getCmisVersion() == CmisVersion.CMIS_1_0) {
            throw new CmisNotSupportedException("This method is not supported for CMIS 1.0 repositories.");
        }

        return new AppendOutputStream(getSession(), this, true, filename, mimeType);
    }

    @Override
    public OutputStream createOverwriteOutputStream(String filename, String mimeType, int bufferSize) {
        if (getSession().getRepositoryInfo().getCmisVersion() == CmisVersion.CMIS_1_0) {
            throw new CmisNotSupportedException("This method is not supported for CMIS 1.0 repositories.");
        }

        return new AppendOutputStream(getSession(), this, true, filename, mimeType, bufferSize);
    }

    @Override
    public OutputStream createAppendOutputStream() {
        if (getSession().getRepositoryInfo().getCmisVersion() == CmisVersion.CMIS_1_0) {
            throw new CmisNotSupportedException("This method is not supported for CMIS 1.0 repositories.");
        }

        return new AppendOutputStream(getSession(), this, false, null, null);
    }

    @Override
    public OutputStream createAppendOutputStream(int bufferSize) {
        if (getSession().getRepositoryInfo().getCmisVersion() == CmisVersion.CMIS_1_0) {
            throw new CmisNotSupportedException("This method is not supported for CMIS 1.0 repositories.");
        }

        return new AppendOutputStream(getSession(), this, false, null, null, bufferSize);
    }

    @Override
    public ObjectId checkIn(boolean major, Map<String, ?> properties, ContentStream contentStream, String checkinComment) {
        return this.checkIn(major, properties, contentStream, checkinComment, null, null, null);
    }
}
