// ***************************************************************************************************************************
// * 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.juneau.examples.rest.petstore;

import static java.text.MessageFormat.*;

import java.io.*;
import java.util.*;

import javax.persistence.*;

import org.apache.juneau.examples.rest.petstore.dto.*;
import org.apache.juneau.examples.rest.petstore.rest.*;
import org.apache.juneau.json.*;
import org.apache.juneau.parser.ParseException;
import org.apache.juneau.rest.client.*;
import org.apache.juneau.utils.*;

/**
 * Pet store database application.
 * <p>
 * Uses JPA persistence to store and retrieve PetStore DTOs.
 * JPA beans are defined in <c>META-INF/persistence.xml</c>.
 *
 * <ul class='seealso'>
 * 	<li class='extlink'>{@source}
 * </ul>
 */
public class PetStoreService extends AbstractPersistenceService {

	//-----------------------------------------------------------------------------------------------------------------
	// Initialization methods.
	//-----------------------------------------------------------------------------------------------------------------

	/**
	 * Initialize the petstore database using JPA.
	 *
	 * @param w Console output.
	 * @return This object (for method chaining).
	 * @throws ParseException Malformed input encountered.
	 * @throws IOException File could not be read from file system.
	 */
	public PetStoreService initDirect(PrintWriter w) throws ParseException, IOException {

		EntityManager em = getEntityManager();
		EntityTransaction et = em.getTransaction();
		JsonParser parser = JsonParser.create().build();

		et.begin();

		for (Pet x : em.createQuery("select X from PetstorePet X", Pet.class).getResultList()) {
			em.remove(x);
			w.println(format("Deleted pet:  id={0}", x.getId()));
		}
		for (Order x : em.createQuery("select X from PetstoreOrder X", Order.class).getResultList()) {
			em.remove(x);
			w.println(format("Deleted order:  id={0}", x.getId()));
		}
		for (User x : em.createQuery("select X from PetstoreUser X", User.class).getResultList()) {
			em.remove(x);
			w.println(format("Deleted user:  username={0}", x.getUsername()));
		}

		et.commit();
		et.begin();

		for (Pet x : parser.parse(getStream("init/Pets.json"), Pet[].class)) {
			x = em.merge(x);
			w.println(format("Created pet:  id={0}, name={1}", x.getId(), x.getName()));
		}
		for (Order x : parser.parse(getStream("init/Orders.json"), Order[].class)) {
			x = em.merge(x);
			w.println(format("Created order:  id={0}", x.getId()));
		}
		for (User x: parser.parse(getStream("init/Users.json"), User[].class)) {
			x = em.merge(x);
			w.println(format("Created user:  username={0}", x.getUsername()));
		}

		et.commit();

		return this;
	}

	/**
	 * Initialize the petstore database by using a remote resource interface against our REST.
	 *
	 * @param w Console output.
	 * @return This object (for method chaining).
	 * @throws ParseException Malformed input encountered.
	 * @throws IOException Thrown by client stream.
	 */
	public PetStoreService initViaRest(PrintWriter w) throws ParseException, IOException {
		JsonParser parser = JsonParser.create().ignoreUnknownBeanProperties().build();

		String port = System.getProperty("juneau.serverPort", "8000");

		try (RestClient rc = RestClient.create().json().rootUrl("http://localhost:" + port).build()) {
			PetStore ps = rc.getRemoteResource(PetStore.class);

			for (Pet x : ps.getPets()) {
				ps.deletePet("apiKey", x.getId());
				w.println(format("Deleted pet:  id={0}", x.getId()));
			}
			for (Order x : ps.getOrders()) {
				ps.deleteOrder(x.getId());
				w.println(format("Deleted order:  id={0}", x.getId()));
			}
			for (User x : ps.getUsers()) {
				ps.deleteUser(x.getUsername());
				w.println(format("Deleted user:  username={0}", x.getUsername()));
			}
			for (CreatePet x : parser.parse(getStream("init/Pets.json"), CreatePet[].class)) {
				long id = ps.postPet(x);
				w.println(format("Created pet:  id={0}, name={1}", id, x.getName()));
			}
			for (Order x : parser.parse(getStream("init/Orders.json"), Order[].class)) {
				long id = ps.placeOrder(x.getPetId(), x.getUsername());
				w.println(format("Created order:  id={0}", id));
			}
			for (User x: parser.parse(getStream("init/Users.json"), User[].class)) {
				ps.postUser(x);
				w.println(format("Created user:  username={0}", x.getUsername()));
			}
		}

		return this;
	}

	//-----------------------------------------------------------------------------------------------------------------
	// Service methods.
	//-----------------------------------------------------------------------------------------------------------------

	/**
	 * Returns the pet with the specified ID.
	 *
	 * @param id The pet ID.
	 * @return The pet with the specified ID.  Never <jk>null</jk>.
	 * @throws IdNotFound If pet was not found.
	 */
	public Pet getPet(long id) throws IdNotFound {
		return find(Pet.class, id);
	}

	/**
	 * Returns the order with the specified ID.
	 *
	 * @param id The order ID.
	 * @return The order with the specified ID.  Never <jk>null</jk>.
	 * @throws IdNotFound If order was not found.
	 */
	public Order getOrder(long id) throws IdNotFound {
		return find(Order.class, id);
	}

	/**
	 * Returns the user with the specified username.
	 *
	 * @param username The username.
	 * @return The user with the specified username.  Never <jk>null</jk>.
	 * @throws InvalidUsername Username was not valid.
	 * @throws IdNotFound If order was not found.
	 */
	public User getUser(String username) throws InvalidUsername, IdNotFound  {
		assertValidUsername(username);
		return find(User.class, username);
	}

	/**
	 * Returns all pets in the database.
	 *
	 * @return All pets in the database.
	 */
	public List<Pet> getPets() {
		return query("select X from PetstorePet X", Pet.class, (SearchArgs)null);
	}

	/**
	 * Returns all orders in the database.
	 *
	 * @return All orders in the database.
	 */
	public List<Order> getOrders() {
		return query("select X from PetstoreOrder X", Order.class, (SearchArgs)null);
	}

	/**
	 * Returns all users in the database.
	 *
	 * @return All users in the database.
	 */
	public List<User> getUsers() {
		return query("select X from PetstoreUser X", User.class, (SearchArgs)null);
	}

	/**
	 * Creates a new pet in the database.
	 *
	 * @param c The pet input data.
	 * @return a new {@link Pet} object.
	 */
	public Pet create(CreatePet c) {
		return merge(new Pet().status(PetStatus.AVAILABLE).apply(c));
	}

	/**
	 * Creates a new order in the database.
	 *
	 * @param c The order input data.
	 * @return a new {@link Order} object.
	 */
	public Order create(CreateOrder c) {
		return merge(new Order().status(OrderStatus.PLACED).apply(c));
	}

	/**
	 * Creates a new user in the database.
	 *
	 * @param c The user input data.
	 * @return a new {@link User} object.
	 */
	public User create(User c) {
		return merge(new User().apply(c));
	}

	/**
	 * Updates a pet in the database.
	 *
	 * @param u The update information.
	 * @return The updated {@link Pet} object.
	 * @throws IdNotFound Pet was not found.
	 */
	public Pet update(UpdatePet u) throws IdNotFound {
		EntityManager em = getEntityManager();
		return merge(em, find(em, Pet.class, u.getId()).apply(u));
	}

	/**
	 * Updates an order in the database.
	 *
	 * @param o The update information.
	 * @return The updated {@link Order} object.
	 * @throws IdNotFound Order was not found.
	 */
	public Order update(Order o) throws IdNotFound {
		EntityManager em = getEntityManager();
		return merge(em, find(em, Order.class, o.getId()).apply(o));
	}

	/**
	 * Updates a user in the database.
	 *
	 * @param u The update information.
	 * @return The updated {@link User} object.
	 * @throws IdNotFound User was not found.
	 * @throws InvalidUsername The username was not valid.
	 */
	public User update(User u) throws IdNotFound, InvalidUsername {
		assertValidUsername(u.getUsername());
		EntityManager em = getEntityManager();
		return merge(em, find(em, User.class, u.getUsername()).apply(u));
	}

	/**
	 * Removes a pet from the database.
	 *
	 * @param id The pet ID.
	 * @throws IdNotFound Pet was not found.
	 */
	public void removePet(long id) throws IdNotFound {
		EntityManager em = getEntityManager();
		remove(em, find(em, Pet.class, id));
	}

	/**
	 * Removes an order from the database.
	 *
	 * @param id The order ID.
	 * @throws IdNotFound Order was not found.
	 */
	public void removeOrder(long id) throws IdNotFound {
		EntityManager em = getEntityManager();
		remove(em, find(em, Order.class, id));
	}

	/**
	 * Removes a user from the database.
	 *
	 * @param username The username.
	 * @throws IdNotFound User was not found.
	 */
	public void removeUser(String username) throws IdNotFound {
		EntityManager em = getEntityManager();
		remove(em, find(em, User.class, username));
	}

	/**
	 * Returns all pets with the specified statuses.
	 *
	 * @param status Pet statuses.
	 * @return Pets with the specified statuses.
	 */
	public Collection<Pet> getPetsByStatus(PetStatus[] status) {
		return getEntityManager()
			.createQuery("select X from PetstorePet X where X.status in :status", Pet.class)
			.setParameter("status", status)
			.getResultList();
	}

	/**
	 * Returns all pets with the specified tags.
	 *
	 * @param tags Pet tags.
	 * @return Pets with the specified tags.
	 * @throws InvalidTag Tag name was invalid.
	 */
	public Collection<Pet> getPetsByTags(String[] tags) throws InvalidTag {
		return getEntityManager()
			.createQuery("select X from PetstorePet X where X.tags in :tags", Pet.class)
			.setParameter("tags", tags)
			.getResultList();
	}

	/**
	 * Returns a summary of pet statuses and counts.
	 *
	 * @return A summary of pet statuses and counts.
	 */
	public Map<PetStatus,Integer> getInventory() {
		Map<PetStatus,Integer> m = new LinkedHashMap<>();
		for (Pet p : getPets()) {
			PetStatus ps = p.getStatus();
			if (! m.containsKey(ps))
				m.put(ps, 1);
			else
				m.put(ps, m.get(ps) + 1);
		}
		return m;
	}

	/**
	 * Returns <jk>true</jk> if the specified username and password is valid.
	 *
	 * @param username The username.
	 * @param password The password.
	 * @return <jk>true</jk> if the specified username and password is valid.
	 */
	public boolean isValid(String username, String password) {
		return getUser(username).getPassword().equals(password);
	}

	//-----------------------------------------------------------------------------------------------------------------
	// Helper methods
	//-----------------------------------------------------------------------------------------------------------------

	private void assertValidUsername(String username) throws InvalidUsername {
		if (username == null || ! username.matches("[\\w\\d]{3,8}"))
			throw new InvalidUsername();
	}

	private InputStream getStream(String fileName) {
		return getClass().getResourceAsStream(fileName);
	}
}