/***************************************************************************
 * Copyright (C) 2003-2007 eXo Platform SAS.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see<http://www.gnu.org/licenses/>.
 ***************************************************************************/
package org.exoplatform.forum.webui;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.portlet.ActionResponse;
import javax.xml.namespace.QName;

import org.exoplatform.container.ExoContainerContext;
import org.exoplatform.forum.ForumUtils;
import org.exoplatform.forum.info.ForumParameter;
import org.exoplatform.forum.info.UIForumPollPortlet;
import org.exoplatform.forum.service.Forum;
import org.exoplatform.forum.service.ForumServiceUtils;
import org.exoplatform.forum.service.UserProfile;
import org.exoplatform.forum.service.Utils;
import org.exoplatform.forum.webui.popup.UIPollForm;
import org.exoplatform.ks.common.UserHelper;
import org.exoplatform.ks.common.webui.BaseEventListener;
import org.exoplatform.ks.common.webui.UIPopupAction;
import org.exoplatform.poll.service.Poll;
import org.exoplatform.poll.service.PollService;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.EventConfig;
import org.exoplatform.webui.core.UIComponent;
import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;
import org.exoplatform.webui.core.model.SelectItemOption;
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.event.EventListener;
import org.exoplatform.webui.form.UIFormRadioBoxInput;

/**
 * Created by The eXo Platform SARL
 * Author : Vu Duy Tu
 *          tu.duy@exoplatform.com
 * Octo 26, 2007 9:48:18 AM 
 */

@ComponentConfig(
    lifecycle = UIFormLifecycle.class ,
    template = "app:/templates/forum/webui/UITopicPoll.gtmpl", 
    events = {
      @EventConfig(listeners = UITopicPoll.VoteActionListener.class),  
      @EventConfig(listeners = UITopicPoll.EditPollActionListener.class) ,
      @EventConfig(listeners = UITopicPoll.RemovePollActionListener.class, confirm="UITopicPoll.msg.confirm-RemovePoll"),
      @EventConfig(listeners = UITopicPoll.ClosedPollActionListener.class),
      @EventConfig(listeners = UITopicPoll.VoteAgainPollActionListener.class)
    }
)
public class UITopicPoll extends BaseForumForm {
  private Poll        poll_;

  private String      categoryId, forumId, topicId;

  private boolean     isAgainVote     = false;

  private boolean     isEditPoll      = false;

  private boolean     canViewEditMenu = false;

  private boolean     userIsBanned    = false;

  private Forum       forum;

  private PollService pollService;

  private String      pollId;

  public UITopicPoll() throws Exception {
    pollService = (PollService) ExoContainerContext.getCurrentContainer().getComponentInstanceOfType(PollService.class);
  }

  public UserProfile getUserProfile() throws Exception {
    userProfile = new UserProfile();
    try {
      userProfile = this.getAncestorOfType(UIForumPortlet.class).getUserProfile();
    } catch (Exception e) {
      try {
        userProfile = getForumService().getDefaultUserProfile(UserHelper.getCurrentUser(), ForumUtils.EMPTY_STR);
      } catch (Exception ex) {
      }
    }
    return userProfile;
  }

  public void setForum(Forum forum) {
    if (forum == null) {
      try {
        this.forum = getForumService().getForum(categoryId, forumId);
      } catch (Exception e) {
      }
    } else {
      this.forum = forum;
    }
  }

  public void updateFormPoll(String categoryId, String forumId, String topicId) throws Exception {
    this.categoryId = categoryId;
    this.forumId = forumId;
    this.topicId = topicId;
    this.isEditPoll = true;
    this.isAgainVote = false;
  }

  @SuppressWarnings("unchecked")
  private void init() throws Exception {
    if (this.hasChildren()) {
      this.removeChild(UIFormRadioBoxInput.class);
      int i = 0;
      while (i < 10) {
        if (this.hasChildren())
          this.removeChild(UIForumCheckBoxInput.class);
        else
          break;
        ++i;
      }
    }
    if (poll_ != null) {
      if (!poll_.getIsMultiCheck()) {
        List<SelectItemOption<String>> options = new ArrayList<SelectItemOption<String>>();
        for (String s : poll_.getOption()) {
          options.add(new SelectItemOption<String>(s, s));
        }
        UIFormRadioBoxInput input = new UIFormRadioBoxInput("vote", "vote", options);
        input.setAlign(1);
        addUIFormInput(input);
      } else {
        for (String s : poll_.getOption()) {
          addUIFormInput(new UIForumCheckBoxInput(s, s, false));
        }
      }
    }
  }

  private Poll getPoll() throws Exception {
    if (!ForumUtils.isEmpty(categoryId)) {
      if (userProfile.getUserRole() == 0 || ForumServiceUtils.hasPermission(this.forum.getModerators(), userProfile.getUserId()))
        this.canViewEditMenu = true;
      else
        this.canViewEditMenu = false;
      pollId = forum.getPath() + ForumUtils.SLASH + topicId + ForumUtils.SLASH + topicId.replace(Utils.TOPIC, Utils.POLL);
      try {
        poll_ = pollService.getPoll(pollId);
      } catch (Exception e) {
      }
      this.init();
      return poll_;
    }
    return null;
  }

  @SuppressWarnings("unused")
  private boolean getIsEditPoll() {
    return isEditPoll;
  }

  public void setEditPoll(boolean isEditPoll) {
    this.isEditPoll = isEditPoll;
  }

  @SuppressWarnings("unused")
  private boolean getCanViewEditMenu() {
    return this.canViewEditMenu;
  }

  @SuppressWarnings("unused")
  private boolean isGuestPermission() throws Exception {
    if (poll_.getIsClosed())
      return true;
    String userVote = userProfile.getUserId();
    userIsBanned = userProfile.getIsBanned();
    if (userIsBanned || userProfile.getUserRole() > 2)
      return true;
    if (ForumUtils.isEmpty(userVote))
      return true;
    if (poll_.getTimeOut() > 0) {
      Date today = new Date();
      if ((today.getTime() - this.poll_.getCreatedDate().getTime()) >= poll_.getTimeOut() * 86400000)
        return true;
    }
    if (this.isAgainVote) {
      return false;
    }
    String[] userVotes = poll_.getUserVote();
    for (String string : userVotes) {
      string = string.substring(0, string.indexOf(":"));
      if (string.equalsIgnoreCase(userVote))
        return true;
    }
    return false;
  }

  @SuppressWarnings("unused")
  private String[] getInfoVote() throws Exception {
    Poll poll = poll_;
    String[] voteNumber = poll.getVote();
    String[] userVotes = poll.getUserVote();
    long size = 0, temp = 1;
    if (!poll.getIsMultiCheck()) {
      size = userVotes.length;
    } else {
      for (int i = 0; i < userVotes.length; i++) {
        size += userVotes[i].split(":").length - 1;
      }
    }
    temp = size;
    if (size == 0)
      size = 1;
    int l = voteNumber.length;
    String[] infoVote = new String[(l + 1)];
    for (int j = 0; j < l; j++) {
      String string = voteNumber[j];
      double tmp = Double.parseDouble(string);
      double k = (tmp * size) / 100;
      int t = (int) Math.round(k);
      string = ForumUtils.EMPTY_STR + (double) t * 100 / size;
      infoVote[j] = string + ":" + t;
    }
    infoVote[l] = ForumUtils.EMPTY_STR + temp;
    if (poll.getIsMultiCheck()) {
      infoVote[l] = String.valueOf(userVotes.length);
    }
    return infoVote;
  }

  @SuppressWarnings("unused")
  private void reloadTopicDetail() {
    UITopicDetailContainer topicDetailContainer = (UITopicDetailContainer) this.getParent();
    topicDetailContainer.getChild(UITopicDetail.class).setIsEditTopic(true);
  }

  static public class VoteActionListener extends EventListener<UITopicPoll> {
    @SuppressWarnings("unchecked")
    public void execute(Event<UITopicPoll> event) throws Exception {
      UITopicPoll topicPoll = event.getSource();
      if (!ForumUtils.isEmpty(topicPoll.pollId)) {
        topicPoll.poll_ = topicPoll.pollService.getPoll(topicPoll.pollId);
      }
      Poll poll = topicPoll.poll_;
      String[] votes;
      String[] setUserVote;
      String userVote = topicPoll.userProfile.getUserId();
      List<UIComponent> children = topicPoll.getChildren();

      // User vote and vote number
      String[] temporary = topicPoll.poll_.getUserVote();
      int size = 0;
      if (temporary != null && temporary.length > 0) {
        size = temporary.length;
      }

      if (!poll.getIsMultiCheck()) {
        UIFormRadioBoxInput radioInput = null;
        for (UIComponent child : children) {
          if (child instanceof UIFormRadioBoxInput) {
            radioInput = (UIFormRadioBoxInput) child;
          }
        }
        if (radioInput.getValue().equalsIgnoreCase("vote")) {
          topicPoll.warning("UITopicPoll.msg.notCheck");
        } else {
          // order number
          List<SelectItemOption<String>> options = new ArrayList<SelectItemOption<String>>();
          options = radioInput.getOptions();
          int i = 0, j = 0;
          for (SelectItemOption<String> option : options) {
            if (option.getValue().equalsIgnoreCase(radioInput.getValue())) {
              j = i;
              break;
            }
            i = i + 1;
          }
          int index = 0;
          if (topicPoll.isAgainVote) {
            setUserVote = new String[size];
            for (int t = 0; t < size; t++) {
              String string = temporary[t].substring(0, temporary[t].length() - 2);
              if (string.equalsIgnoreCase(userVote)) {
                setUserVote[t] = userVote + ":" + j;
                index = t;
              } else {
                setUserVote[t] = temporary[t];
              }
            }
          } else {
            setUserVote = new String[(size + 1)];
            System.arraycopy(temporary, 0, setUserVote, 0, size);
            setUserVote[size] = userVote + ":" + j;
            size = size + 1;
          }
          votes = topicPoll.poll_.getVote();
          double onePercent = (double) 100 / size;
          if (topicPoll.isAgainVote) {
            char tmp = temporary[index].charAt((temporary[index].length() - 1));
            int k = Integer.valueOf(tmp) - 48;
            if (k < votes.length)
              votes[k] = String.valueOf((Double.parseDouble(votes[k]) - onePercent));
            votes[j] = String.valueOf((Double.parseDouble(votes[j]) + onePercent));
          } else {
            i = 0;
            for (String vote : votes) {
              double a = Double.parseDouble(vote);
              if (i == j)
                votes[i] = ForumUtils.EMPTY_STR + ((a - a / size) + onePercent);
              else
                votes[i] = ForumUtils.EMPTY_STR + (a - a / size);
              i = i + 1;
            }
          }
          // save Poll
          poll.setVote(votes);
          poll.setUserVote(setUserVote);
        }
        // multichoice when vote
      } else {
        UIForumCheckBoxInput forumCheckBox = null;
        List<String> listValue = new ArrayList<String>();
        for (UIComponent child : children) {
          if (child instanceof UIForumCheckBoxInput) {
            forumCheckBox = ((UIForumCheckBoxInput) child);
            if (forumCheckBox.isChecked()) {
              listValue.add(forumCheckBox.getName());
            }
          }
        }
        if (!listValue.isEmpty()) {
          votes = topicPoll.poll_.getVote();
          double totalVote = 0;
          double doubleVote[] = new double[votes.length];
          String[] listUserVoted = topicPoll.poll_.getUserVote();
          if (listUserVoted.length > 0) {
            for (String us : listUserVoted) {
              totalVote += us.split(":").length - 1;
            }
          }
          int i = 0;
          int pos = 0;
          if (votes != null && votes.length > 0) {
            for (String v : votes) {
              doubleVote[i++] = Double.parseDouble(v);
            }
          }
          if (totalVote > 0) {
            for (i = 0; i < doubleVote.length; i++) {
              doubleVote[i] = (doubleVote[i] * totalVote) / 100;
            }
          }
          if (!topicPoll.isAgainVote) {
            i = 0;
            pos = size;
            setUserVote = new String[size + 1];
            for (String userHaveVoted : poll.getUserVote())
              setUserVote[i++] = userHaveVoted;
            setUserVote[i] = userVote;
          } else {
            setUserVote = poll.getUserVote();
            int l = setUserVote.length;
            if (l == 0) {
              setUserVote = new String[] { userVote };
            } else {
              for (i = 0; i < l; i++) {
                if (setUserVote[i].split(":")[0].equals(userVote)) {
                  pos = i;
                  break;
                }
              }
              String[] posHaveVoted = (setUserVote[pos].substring(setUserVote[pos].indexOf(":"))).split(":");
              setUserVote[pos] = setUserVote[pos].substring(0, setUserVote[pos].indexOf(":"));
              for (String posVoted : posHaveVoted) {
                if (!ForumUtils.isEmpty(posVoted)) {
                  doubleVote[Integer.parseInt(posVoted)] -= 1;
                  totalVote -= 1;
                }
              }
            }
          }
          i = 0;
          for (String option : topicPoll.poll_.getOption()) {
            if (listValue.contains(option)) {
              doubleVote[i] += 1;
              totalVote += 1;
              setUserVote[pos] += ":" + i;
            }
            i++;
          }
          i = 0;
          for (double dv : doubleVote) {
            if (totalVote > 0 && dv > 0)
              votes[i] = ((dv / totalVote) * 100) + ForumUtils.EMPTY_STR;
            else
              votes[i] = "0.0";
            i++;
          }
          // save votes:
          poll.setUserVote(setUserVote);
          poll.setVote(votes);
        } else {
          topicPoll.warning("UITopicPoll.msg.notCheck");
        }
      }
      topicPoll.pollService.savePoll(poll, false, true);
      topicPoll.isAgainVote = false;
      event.getRequestContext().addUIComponentToUpdateByAjax(topicPoll.getParent());
    }
  }

  static public class EditPollActionListener extends BaseEventListener<UITopicPoll> {
    public void onEvent(Event<UITopicPoll> event, UITopicPoll topicPoll, final String objectId) throws Exception {
      UIPopupAction popupAction;
      try {
        UIForumPortlet forumPortlet = topicPoll.getAncestorOfType(UIForumPortlet.class);
        popupAction = forumPortlet.getChild(UIPopupAction.class);
      } catch (Exception e) {
        UIForumPollPortlet forumPollPortlet = topicPoll.getAncestorOfType(UIForumPollPortlet.class);
        popupAction = forumPollPortlet.getChild(UIPopupAction.class);
      }
      UIPollForm pollForm = popupAction.createUIComponent(UIPollForm.class, null, null);
      String path = topicPoll.categoryId + ForumUtils.SLASH + topicPoll.forumId + ForumUtils.SLASH + topicPoll.topicId;
      pollForm.setTopicPath(path);
      topicPoll.poll_ = topicPoll.getPoll();
      pollForm.setUpdatePoll(topicPoll.poll_, true);
      popupAction.activate(pollForm, 662, 466);
      topicPoll.isEditPoll = true;
    }
  }

  static public class RemovePollActionListener extends EventListener<UITopicPoll> {
    public void execute(Event<UITopicPoll> event) throws Exception {
      UITopicPoll topicPoll = event.getSource();
      topicPoll.pollService.removePoll(topicPoll.poll_.getParentPath() + ForumUtils.SLASH + topicPoll.poll_.getId());
      if (topicPoll.poll_.getIsMultiCheck()) {
        List<UIComponent> children = topicPoll.getChildren();
        for (int i = 0; i < children.size(); i++) {
          topicPoll.removeChild(UIForumCheckBoxInput.class);
        }
      } else {
        topicPoll.removeChild(UIFormRadioBoxInput.class);
      }
      try {
        UITopicDetailContainer topicDetailContainer = (UITopicDetailContainer) topicPoll.getParent();
        topicDetailContainer.getChild(UITopicDetail.class).setIsEditTopic(true);
        topicPoll.isEditPoll = false;
        event.getRequestContext().addUIComponentToUpdateByAjax(topicDetailContainer);
      } catch (Exception e) {
        UIForumPollPortlet forumPollPortlet = topicPoll.getAncestorOfType(UIForumPollPortlet.class);
        topicPoll.setRendered(false);
        ActionResponse actionRes = event.getRequestContext().getResponse();
        ForumParameter param = new ForumParameter();
        param.setRenderPoll(true);
        actionRes.setEvent(new QName("ReLoadPortletEvent"), param);
        event.getRequestContext().addUIComponentToUpdateByAjax(forumPollPortlet);
      }
    }
  }

  static public class VoteAgainPollActionListener extends EventListener<UITopicPoll> {
    public void execute(Event<UITopicPoll> event) throws Exception {
      UITopicPoll topicPoll = event.getSource();
      topicPoll.isAgainVote = true;
      topicPoll.poll_ = topicPoll.getPoll();
      topicPoll.init();
      event.getRequestContext().addUIComponentToUpdateByAjax(topicPoll);
    }
  }

  static public class ClosedPollActionListener extends BaseEventListener<UITopicPoll> {
    public void onEvent(Event<UITopicPoll> event, UITopicPoll topicPoll, final String id) throws Exception {
      if (id.equals("true")) {
        topicPoll.poll_.setIsClosed(false);
        topicPoll.poll_.setTimeOut(0);
      } else {
        topicPoll.poll_.setIsClosed(!topicPoll.poll_.getIsClosed());
      }
      try {
        topicPoll.pollService.setClosedPoll(topicPoll.poll_);
      } catch (Exception e) {
      }
      topicPoll.isAgainVote = false;
      event.getRequestContext().addUIComponentToUpdateByAjax(topicPoll);
    }
  }
}
