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

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReadWriteLock;

import org.apache.sentry.hdfs.service.thrift.TPathChanges;
import org.apache.sentry.hdfs.service.thrift.TPathsDump;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.sentry.hdfs.ServiceConstants.IMAGE_NUMBER_UPDATE_UNINITIALIZED;
import static org.apache.sentry.hdfs.ServiceConstants.SEQUENCE_NUMBER_UPDATE_UNINITIALIZED;

public class UpdateableAuthzPaths implements AuthzPaths, Updateable<PathsUpdate> {
  private static final int MAX_UPDATES_PER_LOCK_USE = 99;
  private static final String UPDATABLE_TYPE_NAME = "path_update";
  private static final Logger LOG = LoggerFactory.getLogger(UpdateableAuthzPaths.class);
  private volatile HMSPaths paths;
  private final AtomicLong seqNum = new AtomicLong(SEQUENCE_NUMBER_UPDATE_UNINITIALIZED);
  private final AtomicLong imgNum = new AtomicLong(IMAGE_NUMBER_UPDATE_UNINITIALIZED);

  public UpdateableAuthzPaths(String[] pathPrefixes) {
    this.paths = new HMSPaths(pathPrefixes);
  }

  UpdateableAuthzPaths(HMSPaths paths) {
    this.paths = paths;
  }

  @Override
  public boolean isUnderPrefix(String[] pathElements) {
    return paths.isUnderPrefix(pathElements);
  }

  @Override
  public Set<String> findAuthzObject(String[] pathElements) {
    return paths.findAuthzObject(pathElements);
  }

  @Override
  public Set<String> findAuthzObjectExactMatches(String[] pathElements) {
    return paths.findAuthzObjectExactMatches(pathElements);
  }

  @Override
  public UpdateableAuthzPaths updateFull(PathsUpdate update) {
    UpdateableAuthzPaths other = getPathsDump().initializeFromDump(
            update.toThrift().getPathsDump());
    other.seqNum.set(update.getSeqNum());
    other.imgNum.set(update.getImgNum());
    return other;
  }

  @Override
  public void updatePartial(Iterable<PathsUpdate> updates, ReadWriteLock lock) {
    lock.writeLock().lock();
    try {
      int counter = 0;
      for (PathsUpdate update : updates) {
        applyPartialUpdate(update);
        if (++counter > MAX_UPDATES_PER_LOCK_USE) {
          counter = 0;
          lock.writeLock().unlock();
          lock.writeLock().lock();
        }
        seqNum.set(update.getSeqNum());

        // Update the image ID only if the update has a new one
        if (imgNum.get() < update.getImgNum()) {
          imgNum.set(update.getImgNum());
        }
        LOG.debug("##### Updated paths seq Num [{}] img Num [{}]", seqNum.get(), imgNum.get());
      }
    } finally {
      lock.writeLock().unlock();
    }
  }

  private void applyPartialUpdate(PathsUpdate update) {
    // Handle alter table rename : will have exactly 2 path changes
    // 1 is add path and the other is del path and oldName != newName
    if (update.getPathChanges().size() == 2) {
      List<TPathChanges> pathChanges = update.getPathChanges();
      TPathChanges newPathInfo = null;
      TPathChanges oldPathInfo = null;
      if (pathChanges.get(0).getAddPathsSize() == 1
          && pathChanges.get(1).getDelPathsSize() == 1) {
        newPathInfo = pathChanges.get(0);
        oldPathInfo = pathChanges.get(1);
      } else if (pathChanges.get(1).getAddPathsSize() == 1
          && pathChanges.get(0).getDelPathsSize() == 1) {
        newPathInfo = pathChanges.get(1);
        oldPathInfo = pathChanges.get(0);
      }
      if (newPathInfo != null && oldPathInfo != null &&
              !newPathInfo.getAuthzObj().equalsIgnoreCase(oldPathInfo.getAuthzObj())) {
        LOG.info("Renaming Object:{} to {}",  oldPathInfo.getAuthzObj(), newPathInfo.getAuthzObj());
        paths.renameAuthzObject(
            oldPathInfo.getAuthzObj(), oldPathInfo.getDelPaths(),
            newPathInfo.getAuthzObj(), newPathInfo.getAddPaths());
        return;
      }
    }

    List<TPathChanges> deletePathChanges = new ArrayList<TPathChanges>();
    List<TPathChanges> addPathChanges = new ArrayList<TPathChanges>();

    for (TPathChanges pathChanges : update.getPathChanges()) {
      if (pathChanges.getDelPaths() != null && pathChanges.getDelPaths().size() != 0) {
        deletePathChanges.add(pathChanges);
      }
      if (pathChanges.getAddPaths() != null && pathChanges.getAddPaths().size() != 0) {
        addPathChanges.add(pathChanges);
      }
    }
    for (TPathChanges pathChanges : deletePathChanges) {
      List<List<String>> delPaths = pathChanges.getDelPaths();
      if (delPaths.size() == 1 && delPaths.get(0).size() == 1
              && delPaths.get(0).get(0).equals(PathsUpdate.ALL_PATHS)) {
        // Remove all paths.. eg. drop table
        LOG.info("Applying Path update. Deleting all paths for authz obj {}", pathChanges.getAuthzObj());
        paths.deleteAuthzObject(pathChanges.getAuthzObj());
      } else {
        LOG.info("Applying Path update. Deleting path for authz object: {} authz path: {}",
            pathChanges.getAuthzObj(), pathChanges.getDelPaths());
        paths.deletePathsFromAuthzObject(pathChanges.getAuthzObj(), pathChanges
                .getDelPaths());
      }
    }
    for (TPathChanges pathChanges : addPathChanges) {
      LOG.info("Applying Path update. Adding path for authz object {} authz path {}",
          pathChanges.getAuthzObj(), pathChanges.getAddPaths());
      applyAddChanges(pathChanges.getAuthzObj(), pathChanges.getAddPaths());
    }
  }

  public void applyAddChanges(String objName, List<List<String>> changes) {
    paths.addPathsToAuthzObject(objName, changes, true);
  }

  @Override
  public long getLastUpdatedSeqNum() {
    return seqNum.get();
  }

  @Override
  public long getLastUpdatedImgNum() {
    return imgNum.get();
  }

  @Override
  public PathsUpdate createFullImageUpdate(long currSeqNum) {
    PathsUpdate pathsUpdate = new PathsUpdate(currSeqNum, true);
    pathsUpdate.toThrift().setPathsDump(getPathsDump().createPathsDump(true));
    return pathsUpdate;
  }

  @Override
  public AuthzPathsDumper<UpdateableAuthzPaths> getPathsDump() {
    return new AuthzPathsDumper<UpdateableAuthzPaths>() {

      @Override
      public TPathsDump createPathsDump(boolean minimizeSize) {
        return UpdateableAuthzPaths.this.paths.getPathsDump().
            createPathsDump(minimizeSize);
      }

      @Override
      public UpdateableAuthzPaths initializeFromDump(TPathsDump pathsDump) {
        return new UpdateableAuthzPaths(UpdateableAuthzPaths.this.paths
            .getPathsDump().initializeFromDump(pathsDump));
      }
    };
  }

  @Override
  public String getUpdateableTypeName() {
    return UPDATABLE_TYPE_NAME;
  }

  @Override
  public String toString() {
    return String.format("%s(%s, %s, %s)", getClass().getSimpleName(), seqNum, imgNum, paths);
  }

  @Override
  public String getSequenceInfo() {
    return String.format("%s(Path: Sequence Number %s, Image Number: %s)", getClass().getSimpleName(), seqNum, imgNum);
  }

  public String dumpContent() {
    return String.format("%s(%s, %s) ", getClass().getSimpleName(), seqNum, imgNum) + paths.dumpContent();
  }
}
