/*
 * Copyright 2010 Google Inc.
 * 
 * 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 com.google.web.bindery.requestfactory.server;

import com.google.gwt.dev.util.collect.HashSet;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

/**
 * Domain object for SimpleFooRequest.
 */
public class SimpleBar implements HasId {
  /**
   * DO NOT USE THIS UGLY HACK DIRECTLY! Call {@link #get} instead.
   */
  private static Map<String, SimpleBar> jreTestSingleton = new HashMap<String, SimpleBar>();

  private static long nextId = 2L;

  static {
    try {
    reset();
    } catch (Throwable t) {
      t.printStackTrace();
    }
  }

  public static Long countSimpleBar() {
    return (long) get().size();
  }

  public static List<SimpleBar> findAll() {
    return new ArrayList<SimpleBar>(get().values());
  }

  public static Set<SimpleBar> findAsSet() {
    return new HashSet<SimpleBar>(get().values());
  }

  public static SimpleBar findSimpleBar(String id) {
    return findSimpleBarById(id);
  }

  /**
   * Returns <code>null</code> if {@link #findFails} is <code>true</code>.
   */
  public static SimpleBar findSimpleBarById(String id) {
    SimpleBar toReturn = get().get(id);
    return (toReturn == null || toReturn.findFails) ? null : toReturn;
  }

  @SuppressWarnings("unchecked")
  public static synchronized Map<String, SimpleBar> get() {
    HttpServletRequest req = RequestFactoryServlet.getThreadLocalRequest();
    if (req == null) {
      // May be in a JRE test case, use the the singleton
      return jreTestSingleton;
    } else {
      /*
       * This will not behave entirely correctly unless we have a servlet filter
       * that doesn't allow any requests to be processed unless they're
       * associated with an existing session.
       */
      Map<String, SimpleBar> value = (Map<String, SimpleBar>) req.getSession().getAttribute(
          SimpleBar.class.getCanonicalName());
      if (value == null) {
        value = resetImpl();
      }
      return value;
    }
  }

  public static SimpleBar getSingleton() {
    return findSimpleBar("1L");
  }

  public static void reset() {
    resetImpl();
  }

  public static synchronized Map<String, SimpleBar> resetImpl() {
    Map<String, SimpleBar> instance = new HashMap<String, SimpleBar>();
    // fixtures
    SimpleBar s1 = new SimpleBar();
    s1.setId("1L");
    s1.isNew = false;
    instance.put(s1.getId(), s1);

    SimpleBar s2 = new SimpleBar();
    s2.setId("999L");
    s2.isNew = false;
    instance.put(s2.getId(), s2);

    HttpServletRequest req = RequestFactoryServlet.getThreadLocalRequest();
    if (req == null) {
      jreTestSingleton = instance;
    } else {
      req.getSession().setAttribute(SimpleBar.class.getCanonicalName(),
          instance);
    }
    return instance;
  }

  public static SimpleBar returnFirst(List<SimpleBar> list) {
    SimpleBar toReturn = list.get(0);
    return toReturn;
  }

  Integer version = 1;

  private String id = "999L";
  private boolean findFails;
  private boolean isNew = true;
  private boolean unpersisted;
  private String userName;

  public SimpleBar() {
    version = 1;
    userName = "FOO";
  }

  public void delete() {
    get().remove(getId());
  }

  public Boolean getFindFails() {
    return findFails;
  }

  public String getId() {
    return unpersisted ? null : id;
  }

  public Boolean getUnpersisted() {
    return unpersisted;
  }

  public String getUserName() {
    return userName;
  }

  public Integer getVersion() {
    return unpersisted ? null : version;
  }

  public void persist() {
    if (isNew) {
      setId(Long.toString(nextId++));
      isNew = false;
      get().put(getId(), this);
    }
    version++;
  }

  public SimpleBar persistAndReturnSelf() {
    persist();
    return this;
  }

  public void setFindFails(Boolean fails) {
    this.findFails = fails;
  }

  public void setId(String id) {
    this.id = id;
  }

  public void setUnpersisted(Boolean unpersisted) {
    this.unpersisted = unpersisted;
  }

  public void setUserName(String userName) {
    this.userName = userName;
  }

  public void setVersion(Integer version) {
    this.version = version;
  }
}
