/*
 * libjingle
 * Copyright 2004--2005, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/examples/call/discoitemsquerytask.h"
#include "talk/examples/call/voicemailjidrequester.h"
#include "talk/base/scoped_ptr.h"
#include "talk/xmpp/constants.h"

namespace buzz {

VoicemailJidRequester::VoicemailJidRequester(talk_base::Task* parent,
                                             const Jid& their_jid,
                                             const Jid& my_jid) : Task(parent),
                                             their_jid_(their_jid),
                                             my_jid_(my_jid),
                                             done_with_query_(false) {
  parent_ = parent;
}

int VoicemailJidRequester::ProcessStart() {
  // Start first query to node='voicemail'
  DiscoItemsQueryTask* disco_items_task = new DiscoItemsQueryTask(this,
      STR_VOICEMAIL, their_jid_.BareJid());
  disco_items_task->SignalGotDiscoItems.connect(this,
      &VoicemailJidRequester::OnFirstVoicemailJidSuccess);
  disco_items_task->SignalDiscoItemsError.connect(this,
      &VoicemailJidRequester::OnFirstVoicemailJidError);
  disco_items_task->Start();
  return STATE_BLOCKED;
}

void VoicemailJidRequester::OnFirstVoicemailJidError(buzz::Jid jid,
    const XmlElement* xml_element) {
  // First query gave us an error - try second query to node='outgoingvoicemail'
  // and send it to your own jid
  StartSecondQuery();
}

void VoicemailJidRequester::OnFirstVoicemailJidSuccess(buzz::Jid jid,
    const XmlElement* xml_element) {
  // Process the XML and fire the appropriate signals.  If the xml was valid,
  // then we're done with queries.  If it wasn't valid, then start the second
  // query.
  bool valid_xml = ProcessVoicemailXml(xml_element);
  if (valid_xml) {
    done_with_query_ = true;
    Wake();
  } else {
    StartSecondQuery();
  }
}

void VoicemailJidRequester::OnSecondVoicemailJidError(buzz::Jid jid,
    const XmlElement* xml_element) {
  SignalVoicemailJidError(their_jid_);
  done_with_query_ = true;
  Wake();
}

void VoicemailJidRequester::OnSecondVoicemailJidSuccess(buzz::Jid jid,
    const XmlElement* xml_element) {
  // Whether this is good xml or bad, we're still done with the query
  bool valid_xml = ProcessVoicemailXml(xml_element);
  if (!valid_xml) {
    SignalVoicemailJidError(their_jid_);
  }
  done_with_query_ = true;
  Wake();
}


void VoicemailJidRequester::StartSecondQuery() {
  // Send a query to your own jid to get the voicemail jid
  DiscoItemsQueryTask* disco_items_task = new DiscoItemsQueryTask(this,
      STR_OUTGOINGVOICEMAIL, my_jid_.BareJid());
  disco_items_task->SignalGotDiscoItems.connect(this,
      &VoicemailJidRequester::OnSecondVoicemailJidSuccess);
  disco_items_task->SignalDiscoItemsError.connect(this,
      &VoicemailJidRequester::OnSecondVoicemailJidError);
  disco_items_task->Start();
}

int VoicemailJidRequester::Process(int state) {
  if (done_with_query_) {
    return STATE_DONE;
  } else {
    return talk_base::Task::Process(state);
  }
}

bool VoicemailJidRequester::ProcessVoicemailXml(const XmlElement* xml_element) {
  if (!xml_element) {
    return false;
  }
  const std::string& node_name = xml_element->Attr(QN_NODE);
  // Verify that it's one of the two nodes - we don't really care which one
  if (node_name != "voicemail" &&
      node_name != "outgoingvoicemail") {
    return false;
  }

  const XmlElement* item = xml_element->FirstNamed(QN_DISCO_ITEM);
  if (item) {
    const std::string& jid_str = item->Attr(QN_JID);
    buzz::Jid voicemail_jid(jid_str);
    SignalGotVoicemailJid(their_jid_, voicemail_jid);
    return true;
  }
  return false;
}
}
