/*
 * 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.jackrabbit;

import org.apache.jackrabbit.SessionImpl.Context;
import org.apache.jackrabbit.json.FullJsonParser;
import org.apache.jackrabbit.json.JsonValue;
import org.apache.jackrabbit.json.JsonValue.JsonObject;
import org.apache.jackrabbit.json.UnescapingJsonTokenizer;
import org.apache.jackrabbit.mk.api.MicroKernel;
import org.xml.sax.ContentHandler;

import javax.jcr.NamespaceRegistry;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Workspace;
import javax.jcr.lock.LockManager;
import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.observation.ObservationManager;
import javax.jcr.query.QueryManager;
import javax.jcr.version.Version;
import javax.jcr.version.VersionManager;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;

public class WorkspaceImpl implements Workspace {
    public static final String DEFAULT_WORKSPACE_NAME = "default";

    private final Context sessionContext;

    private WorkspaceImpl(Context sessionContext) {
        this.sessionContext = sessionContext;
    }

    public static Workspace create(Context sessionContext) {
        return new WorkspaceImpl(sessionContext);
    }

    @Override
    public Session getSession() {
        return sessionContext.getSession();
    }

    @Override
    public String getName() {
        return sessionContext.getWorkspaceName();
    }

    @Override
    public void copy(String srcAbsPath, String destAbsPath) throws RepositoryException {
        // todo implement copy
    }

    @Override
    public void copy(String srcWorkspace, String srcAbsPath, String destAbsPath) throws RepositoryException {
        // todo implement copy
    }

    @Override
    public void clone(String srcWorkspace, String srcAbsPath, String destAbsPath, boolean removeExisting)
            throws RepositoryException {
        
        // todo implement clone
    }

    @Override
    public void move(String srcAbsPath, String destAbsPath) throws RepositoryException {
        // todo implement move
    }

    @Override
    public void restore(Version[] versions, boolean removeExisting) throws RepositoryException {
        // todo implement restore
    }

    @Override
    public LockManager getLockManager() throws RepositoryException {
        // todo implement getLockManager
        throw new UnsupportedRepositoryOperationException("getLockManager");
    }

    @Override
    public QueryManager getQueryManager() throws RepositoryException {
        // todo implement getQueryManager
        throw new UnsupportedRepositoryOperationException("getQueryManager");
    }

    @Override
    public NamespaceRegistry getNamespaceRegistry() throws RepositoryException {
        // todo implement getNamespaceRegistry
        throw new UnsupportedRepositoryOperationException("getNamespaceRegistry");
    }

    @Override
    public NodeTypeManager getNodeTypeManager() throws RepositoryException {
        // todo implement getNodeTypeManager
        throw new UnsupportedRepositoryOperationException("getNodeTypeManager");
    }

    @Override
    public ObservationManager getObservationManager() throws RepositoryException {
        // todo implement getObservationManager
        throw new UnsupportedRepositoryOperationException("getObservationManager");
    }

    @Override
    public VersionManager getVersionManager() throws RepositoryException {
        // todo implement getVersionManager
        throw new UnsupportedRepositoryOperationException("getVersionManager");
    }

    @Override
    public String[] getAccessibleWorkspaceNames() throws RepositoryException {
        MicroKernel microKernel = sessionContext.getMicrokernel();
        String revision = sessionContext.getRevision();
        String json = microKernel.getNodes("/", revision, 0, 0, -1, null);
        JsonObject jsonObject = FullJsonParser.parseObject(new UnescapingJsonTokenizer(json));

        List<String> workspaces = new ArrayList<String>();
        for (Entry<String, JsonValue> entry : jsonObject.value().entrySet()) {
            if (entry.getValue().isObject()) {
                workspaces.add(entry.getKey());
            }
        }

        return workspaces.toArray(new String[workspaces.size()]);
    }

    @Override
    public ContentHandler getImportContentHandler(String parentAbsPath, int uuidBehavior)
            throws RepositoryException {
        
        // todo implement getImportContentHandler
        throw new UnsupportedRepositoryOperationException("getImportContentHandler");
    }

    @Override
    public void importXML(String parentAbsPath, InputStream in, int uuidBehavior) throws IOException,
            RepositoryException {
        
        // todo implement importXML
    }

    @Override
    public void createWorkspace(String name) throws RepositoryException {
        createWorkspace(sessionContext.getMicrokernel(), name);
    }

    @Override
    public void createWorkspace(String name, String srcWorkspace) throws RepositoryException {
        // todo implement createWorkspace
    }

    @Override
    public void deleteWorkspace(String name) throws RepositoryException {
        MicroKernel microKernel = sessionContext.getMicrokernel();
        String revision = microKernel.getHeadRevision();
        microKernel.commit("/", "- \"" + name + '\"', revision, null);
    }

    //------------------------------------------< internal >---

    static void createWorkspace(MicroKernel microKernel,String name) {
        String revision = microKernel.getHeadRevision();
        microKernel.commit("/", "+ \"" + name + "\" : {}", revision, null);
    }

}
