/*******************************************************************************
 * Copyright (c) 2013 Juuso Vilmunen.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 *     Juuso Vilmunen - initial API and implementation
 ******************************************************************************/
package waazdoh.common.testing;

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

import waazdoh.common.WStringID;
import waazdoh.common.WUserID;
import waazdoh.common.WLogger;
import waazdoh.common.client.WCachingObjectsService;
import waazdoh.common.client.WMemoryBeanStorage;
import waazdoh.common.client.WServiceClient;
import waazdoh.common.service.ObjectsService;
import waazdoh.common.service.StorageAreaService;
import waazdoh.common.service.UsersService;
import waazdoh.common.vo.AppLoginVO;
import waazdoh.common.vo.LoginVO;
import waazdoh.common.vo.ObjectVO;
import waazdoh.common.vo.ProfileVO;
import waazdoh.common.vo.ReturnVO;
import waazdoh.common.vo.StorageAreaVO;
import waazdoh.common.vo.UserVO;

public final class StaticService implements WServiceClient {
	private WUserID userid;
	private StorageAreaService storagearea;
	private UsersService users;
	private ObjectsService objects;
	private String session;
	private String username;

	private static Map<String, ObjectVO> data = new HashMap<String, ObjectVO>();
	private static Map<String, String> storage = new HashMap<>();
	private static Map<String, UserVO> userlist = new HashMap<>();
	private static Map<String, AppLoginVO> applogins = new HashMap<>();

	private WLogger logger = WLogger.getLogger(this);

	public StaticService(String username1) {
		this.username = username1;
	}

	@Override
	public void setAuthenticationToken(String session) {
		if (session.length() == 0) {
			this.session = null;
			this.userid = null;
		} else {
			this.session = session;

			this.userid = new WUserID(new WStringID().toString());

			UserVO uservo = new UserVO();
			uservo.setUsername(username);
			uservo.setUserid(userid.toString());
			userlist.put(userid.toString(), uservo);
		}
	}

	@Override
	public String getAuthenticationToken() {
		return session;
	}

	@Override
	public UserVO getUser(String username) {
		UserVO vo = new UserVO();
		vo.setUsername(username);
		return vo;
	}

	@Override
	public UserVO getUser() {
		if (userid != null) {
			UserVO vo = new UserVO();
			vo.setUserid(this.userid.toString());
			vo.setUsername(this.username);
			return vo;
		} else {
			return null;
		}
	}

	@Override
	public ObjectsService getObjects() {
		if (objects == null) {
			objects = new WCachingObjectsService(new ObjectsServiceImplementation(), new WMemoryBeanStorage());
		}

		return objects;
	}

	@Override
	public UsersService getUsers() {
		if (users == null) {
			users = new UsersServiceImplementation();
		}
		return users;
	}

	@Override
	public StorageAreaService getStorageArea() {
		if (storagearea == null) {
			storagearea = new StorageAreaServiceImplementation();
		}
		return storagearea;
	}

	public String createSession() {
		session = UUID.randomUUID().toString();
		return session;
	}

	private final class StorageAreaServiceImplementation implements StorageAreaService {
		@Override
		public ReturnVO write(StorageAreaVO vo) {
			storage.put(getPath(vo.getPath()), vo.getData());
			return ReturnVO.getTrue();
		}

		private String getPath(String username, String path) {
			String p = username + "/" + path;
			return fixPath(p);
		}

		private String getPath(String path) {
			return getPath(username, path);
		}

		@Override
		public StorageAreaVO read(StorageAreaVO vo) {
			vo.setData(storage.get(getPath(vo.getUsername(), vo.getPath())));
			return vo;
		}

		@Override
		public List<String> searchValue(String value) {
			List<String> list = new ArrayList<String>();

			Set<String> ks = storage.keySet();
			for (String string : ks) {
				String listvalue = storage.get(string);
				if (listvalue.equals(value)) {
					list.add(fixPath(string));
				}
			}
			return list;
		}

		@Override
		public List<String> list(StorageAreaVO vo) {
			String path = fixPath(username + "/" + vo.getPath());

			List<String> list = new ArrayList<String>();

			Set<String> ks = storage.keySet();
			for (String string : ks) {
				if (string.startsWith(path)) {
					String subpath = string.substring(path.length()).replace("/", "");
					list.add(subpath);
				}
			}
			return list;
		}

		private String fixPath(String path) {
			if (path.charAt(0) != '/') {
				path = "/" + path;
			}

			path = path.replace("//", "/");

			return path;
		}

		@Override
		public List<String> listNewItems(String path, int start, int count) {
			return list(new StorageAreaVO(path));
		}
	}

	private final class ObjectsServiceImplementation implements ObjectsService {
		@Override
		public ReturnVO write(String objectid, String testdata) {
			ObjectVO value = new ObjectVO(testdata);
			value.setId(objectid);
			data.put(objectid, value);
			return ReturnVO.getTrue();
		}

		@Override
		public List<ObjectVO> search(String search, int i, int j) {
			List<ObjectVO> ret = new ArrayList<>();

			for (String key : data.keySet()) {
				ObjectVO odata = data.get(key);
				if (odata.toObject().toYaml().contains(search)) {
					ret.add(odata);
				}
			}

			return ret;
		}

		@Override
		public ObjectVO read(String string) {
			return data.get(string);
		}

		@Override
		public ReturnVO publish(String objectid) {
			return ReturnVO.get(data.get(objectid) != null);
		}

		@Override
		public ReturnVO error(String id, String error) {
			// TODO Auto-generated method stub
			return ReturnVO.get(false);
		}
	}

	private final class UsersServiceImplementation implements UsersService {
		@Override
		public List<UserVO> search(String string, int i) {
			return new ArrayList<UserVO>();
		}

		@Override
		public void follow(String userid) {
		}

		@Override
		public List<String> getFollowing() {
			return new ArrayList<String>();
		}

		@Override
		public ReturnVO saveProfile(ProfileVO profile) {
			return ReturnVO.get(false);
		}

		@Override
		public AppLoginVO requestAppLogin() {
			AppLoginVO login = new AppLoginVO();
			String id = new WStringID().toString();
			login.setSessionid(id);
			login.setId(id);
			login.setUrl("not a real url");
			applogins.put(id, login);
			return login;
		}

		@Override
		public void registerOAuthService(String string, String string2) {
			// TODO Auto-generated method stub

		}

		@Override
		public UserVO getWithName(String username) {
			for (UserVO u : userlist.values()) {
				if (u.getUsername().equals(username)) {
					return u;
				}
			}

			return UserVO.getFalse();
		}

		@Override
		public UserVO getUser(String userid) {
			return userlist.get(userid);
		}

		@Override
		public List<UserVO> newUsers(int count) {
			return new ArrayList<>(userlist.values());
		}

		@Override
		public ProfileVO getProfile() {
			ProfileVO p = new ProfileVO();
			p.setText("profile " + username);
			return p;
		}

		@Override
		public ReturnVO denyApplication(String appid) {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public UserVO checkSession() {
			if (userid != null) {
				return userlist.get(userid.toString());
			} else {
				return null;
			}
		}

		@Override
		public ReturnVO checkInvitatation(String string) {
			// TODO Auto-generated method stub
			return ReturnVO.get(false);
		}

		@Override
		public AppLoginVO checkAppLogin(String id) {
			return applogins.get(id);
		}

		@Override
		public LoginVO authenticateOAuth(LoginVO vo) {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public ReturnVO acceptApplication(String appid) {
			// TODO Auto-generated method stub
			return null;
		}
	}
}
