import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.Declarable;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.RegionFactory;
import com.gemstone.gemfire.cache.RegionShortcut;

import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionContext;

import java.util.Properties;

public class DestroyRegionFunction implements Function, Declarable {

  private final Cache cache;
  
  private final Region<String,RegionAttributes> regionAttributesMetadataRegion;

  private static final String REGION_ATTRIBUTES_METADATA_REGION = "__regionAttributesMetadata";
  
  public enum Status {SUCCESSFUL, UNSUCCESSFUL, DOESNT_EXIST};

  public DestroyRegionFunction() {
    this.cache = CacheFactory.getAnyInstance();
    this.regionAttributesMetadataRegion = createRegionAttributesMetadataRegion();
  }

  public void execute(FunctionContext context) {
    String regionName = (String) context.getArguments();

    // Destroy region
    Status status = destroyRegion(regionName);

    // Return status
    context.getResultSender().lastResult(status);
  }
  
  private Status destroyRegion(String regionName) {
    Status status = Status.SUCCESSFUL;
    Region region = this.cache.getRegion(regionName);
    if (region == null) {
      status = Status.DOESNT_EXIST;
    } else {
      // Destroy the attributes from the metadata region.
      // The afterDestroy callback will actually destroy the region.
      this.regionAttributesMetadataRegion.destroy(regionName);
      
      // Retrieve the region after destroying it
      region = this.cache.getRegion(regionName);
      if (region != null) {
        status = Status.UNSUCCESSFUL;
      }
    }
    return status;
  }
  
  private Region<String,RegionAttributes> createRegionAttributesMetadataRegion() {
    Region<String, RegionAttributes> metaRegion = this.cache.getRegion(REGION_ATTRIBUTES_METADATA_REGION);
    if (metaRegion == null) {
      RegionFactory<String, RegionAttributes> factory = cache.createRegionFactory(RegionShortcut.REPLICATE);
      factory.addCacheListener(new CreateRegionCacheListener());
      metaRegion = factory.create(REGION_ATTRIBUTES_METADATA_REGION);
    }
    return metaRegion;
  }

  public String getId() {
    return getClass().getSimpleName();
  }

  public boolean optimizeForWrite() {
    return false;
  }

  public boolean isHA() {
    return true;
  }

  public boolean hasResult() {
    return true;
  }

  public void init(Properties properties) {
  }
}

