/*
 * 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.openmeetings.data.conference.dao;

import org.asteriskjava.manager.ManagerConnection;
import org.asteriskjava.manager.ManagerConnectionFactory;
import org.asteriskjava.manager.ResponseEvents;
import org.asteriskjava.manager.action.ConfbridgeListAction;
import org.asteriskjava.manager.action.DbDelAction;
import org.asteriskjava.manager.action.DbDelTreeAction;
import org.asteriskjava.manager.action.DbGetAction;
import org.asteriskjava.manager.action.DbPutAction;
import org.asteriskjava.manager.action.EventGeneratingAction;
import org.asteriskjava.manager.action.ManagerAction;
import org.asteriskjava.manager.response.ManagerError;
import org.asteriskjava.manager.response.ManagerResponse;
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;

public class SipDao {
	private static final Logger log = Red5LoggerFactory.getLogger(SipDao.class);
	public static final String ASTERISK_OM_FAMILY = "openmeetings";
	public static final String ASTERISK_OM_KEY = "rooms";
	private String sipHostname;
	private int sipPort;
	private String sipUsername;
	private String sipPassword;
	private ManagerConnectionFactory factory;
	private ManagerConnection connection;

	@SuppressWarnings("unused")
	private SipDao() {
		// prohibited default constructor
	}

	public SipDao(String sipHostname, int sipPort, String sipUsername, String sipPassword) {
		this.sipHostname = sipHostname;
		this.sipPort = sipPort;
		this.sipUsername = sipUsername;
		this.sipPassword = sipPassword;
		factory = new ManagerConnectionFactory(this.sipHostname, this.sipPort, this.sipUsername, this.sipPassword);
		connection = factory.createManagerConnection(); // TODO secure
	}

	private ManagerResponse exec(ManagerAction action) {
		if (connection == null) {
			log.warn("There is no Asterisk configured");
			return null;
		}
		try {
			connection.login();
			ManagerResponse r = connection.sendAction(action);
			connection.logoff();
			if (log.isDebugEnabled() && r != null) {
				log.debug(r.toString());
			}
			return (r instanceof ManagerError) ? null : r;
		} catch (Exception e) {
			if (log.isDebugEnabled()) {
				log.error("Error while executing ManagerAction: " + action, e);
			}
		}
		return null;
	}

	private ResponseEvents execEvent(EventGeneratingAction action) {
		if (connection == null) {
			log.warn("There is no Asterisk configured");
			return null;
		}
		try {
			connection.login("on");
			ResponseEvents r = connection.sendEventGeneratingAction(action);
			connection.logoff();
			if (log.isDebugEnabled() && r != null) {
				log.debug(r.getResponse().toString());
			}
			return (r == null || r.getResponse() instanceof ManagerError) ? null : r;
		} catch (Exception e) {
			if (log.isDebugEnabled()) {
				log.error("Error while executing EventGeneratingAction: " + action, e);
			}
		}
		return null;
	}

	private String getKey(String confno) {
		return ASTERISK_OM_KEY + "/" + confno;
	}

	public String get(String confno) {
		String pin = null;
		DbGetAction da = new DbGetAction(ASTERISK_OM_FAMILY, getKey(confno));
		ManagerResponse r = exec(da);
		if (r != null) {
			pin = r.getResponse();
		}
		return pin;
	}

	public void update(String confno, String pin) {
		delete(confno);
		DbPutAction da = new DbPutAction(ASTERISK_OM_FAMILY, getKey(confno), pin);
		exec(da);
	}

	public void delete() {
		DbDelTreeAction da = new DbDelTreeAction(ASTERISK_OM_FAMILY, ASTERISK_OM_KEY);
		exec(da);
	}

	public void delete(String confno) {
		DbDelAction da = new DbDelAction(ASTERISK_OM_FAMILY, getKey(confno));
		exec(da);
	}

	public Integer countUsers(String confno) {
		if (confno == null) {
			return null;
		}
		ConfbridgeListAction da = new ConfbridgeListAction(confno);
		ResponseEvents r = execEvent(da);
		if (r != null) {
			log.debug("SipDao::countUsers size == " + r.getEvents().size());
			// "- 1" here means: ListComplete event 
			return r.getEvents().size() - 1; // TODO check if was successfull
		}
		return 0;
	}
}
