/**
 * Copyright 2013 David Rusek <dave dot rusek at gmail dot com>
 *
 * 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 org.robotninjas.barge;

import com.google.common.base.Optional;
import com.google.inject.PrivateModule;
import org.jetlang.fibers.Fiber;
import org.jetlang.fibers.PoolFiberFactory;
import org.robotninjas.barge.log.LogModule;
import org.robotninjas.barge.rpc.Client;
import org.robotninjas.barge.state.Raft;
import org.robotninjas.barge.state.StateModule;

import javax.annotation.concurrent.Immutable;
import java.io.File;
import java.util.concurrent.Executor;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static java.util.concurrent.Executors.newCachedThreadPool;

@Immutable
class RaftCoreModule extends PrivateModule {

  private static final long DEFAULT_TIMEOUT = 225;

  private final long timeout;
  private final ClusterConfig config;
  private final File logDir;
  private final StateMachine stateMachine;
  private final Executor executor;

  private RaftCoreModule(Builder builder) {
    this.config = builder.config.get();
    this.timeout = builder.timeout;
    this.logDir = builder.logDir.get();
    this.stateMachine = builder.stateMachine.get();
    this.executor = builder.executor.or(newCachedThreadPool());
  }

  @Override
  protected void configure() {

    install(new StateModule(timeout));

    PoolFiberFactory fiberFactory = new PoolFiberFactory(executor);

    Fiber raftFiber = fiberFactory.create(new BatchExecutor());
    raftFiber.start();
    bind(Fiber.class)
        .annotatedWith(RaftExecutor.class)
        .toInstance(raftFiber);

    Fiber stateMachineFiber = fiberFactory.create(new BatchExecutor());
    stateMachineFiber.start();

    install(new LogModule(logDir, stateMachine, stateMachineFiber));

    bind(ClusterConfig.class)
        .toInstance(config);

    bind(Client.class)
        .asEagerSingleton();

    expose(Raft.class);

  }

  public static Builder builder() {
    return new Builder();
  }

  public static class Builder {

    private long timeout = DEFAULT_TIMEOUT;
    private Optional<Executor> executor = Optional.absent();
    private Optional<ClusterConfig> config = Optional.absent();
    private Optional<StateMachine> stateMachine = Optional.absent();
    private Optional<File> logDir = Optional.absent();

    private Builder() {

    }

    public Builder withTimeout(long timeout) {
      this.timeout = timeout;
      return this;
    }

    public Builder withExecutor(Executor executor) {
      this.executor = Optional.of(executor);
      return this;
    }

    public Builder withConfig(ClusterConfig config) {
      this.config = Optional.of(config);
      return this;
    }

    public Builder withStateMachine(StateMachine stateMachine) {
      this.stateMachine = Optional.of(stateMachine);
      return this;
    }

    public Builder withLogDir(File logDir) {
      this.logDir = Optional.of(logDir);
      return this;
    }

    public RaftCoreModule build() {
      checkState(config.isPresent());
      checkState(stateMachine.isPresent());
      checkState(logDir.isPresent());
      checkArgument(timeout > 0);
      return new RaftCoreModule(this);
    }

  }

}

@@ -1297,16 +1297,23 @@
 mutable%0A
+public 
 class Ra

Make RaftCoreModule public