package jp.sourceforge.shovel.device.impl;

import static jp.sourceforge.shovel.AvailabilityType.*;

import org.seasar.framework.container.S2Container;

import jp.sourceforge.shovel.device.IDelayExecutorContext;
import jp.sourceforge.shovel.device.IMobilePhoneWrapper;
import jp.sourceforge.shovel.entity.IDevice;
import jp.sourceforge.shovel.entity.IDirectMessage;
import jp.sourceforge.shovel.entity.IFavorite;
import jp.sourceforge.shovel.entity.IFriendship;
import jp.sourceforge.shovel.entity.IStatus;
import jp.sourceforge.shovel.entity.IStatusWrapper;
import jp.sourceforge.shovel.entity.IUser;
import jp.sourceforge.shovel.exception.ApplicationException;
import jp.sourceforge.shovel.logic.IDirectoryLogic;
import jp.sourceforge.shovel.logic.IShovelLogic;

public class MobilePhoneWrapperImpl implements IMobilePhoneWrapper {
    final String source_ = "mobile web";
    
    public String getDisplayName() {
        return null;
    }
    public void setDisplayName(String displayName) {
    }
    public String getAddress() {
        return null;
    }
    public String getExecutorId() {
        return "mobilePhone";
    }
    public boolean isConnected() {
        return true;
    }
    public void setProperty(String key, String value) {
    }
    
    public void connect() throws ApplicationException {
    }
    public void disconnect() {
    }
    public void execute(IDelayExecutorContext context) throws ApplicationException {
        if (!context.isCommit()) {
            return;
        }
        
        IDirectoryLogic directoryLogic = getDirectoryLogic();
        IShovelLogic shovelLogic = getShovelLogic();
        
        switch (context.getDelayExecutionType()) {
        case UPDATE_STATUS:
            IStatus status = context.getStatus();
            updateStatus(status);
            break;
        case DESTROY_STATUS:
            status = context.getStatus();
            directoryLogic.decrementStatuses(status.getSenderId());
            directoryLogic.decrementFavoritesAll(status.getSenderId());
            shovelLogic.clearStatusReference(status.getStatusId());
            shovelLogic.destroyStatus(status.getStatusId(), false);
            break;
        case CREATE_FAVORITE:
            IFavorite favorite = context.getFavorite();
            status = shovelLogic.getStatus(favorite.getStatusId());
            directoryLogic.incrementFavorites(favorite.getUserId());
            if (status.getSenderId() != favorite.getUserId()) {
                directoryLogic.incrementGivenFavorites(status.getSenderId());
            }
            shovelLogic.createFavorite(favorite.getStatusId(), favorite.getUserId(), false);
            break;
        case DESTROY_FAVORITE:
            favorite = context.getFavorite();
            status = shovelLogic.getStatus(favorite.getStatusId());
            directoryLogic.decrementFavoritesAll(favorite.getUserId());
            if (status.getSenderId() != favorite.getUserId()) {
                directoryLogic.decrementGivenFavorites(status.getSenderId());
            }
            shovelLogic.destroyFavorite(favorite.getStatusId(), favorite.getUserId(), false);
            break;
        case SEND_DIRECT_MESSAGE:
            IDirectMessage directMessage = context.getDirectMessage();
            directoryLogic.incrementDirectMessages(directMessage.getRecipientId());
            shovelLogic.createDirectMessage(directMessage.getText(), source_,
                    directMessage.getSenderId(), directMessage.getRecipientId(), false);
            break;
        case DESTROY_SENT:
            directMessage = context.getDirectMessage();
            shovelLogic.destroyDirectMessage(directMessage.getDirectMessageId(), true, false);
            break;
        case DESTROY_INBOX:
            directMessage = context.getDirectMessage();
            directoryLogic.decrementDirectMessages(directMessage.getRecipientId());
            shovelLogic.destroyDirectMessage(directMessage.getDirectMessageId(), false, false);
            break;
        case FOLLOW_FRIEND:
            IFriendship friend = context.getFriend();
            IUser active = directoryLogic.getUser(friend.getActiveId());
            shovelLogic.createFriendship(friend.getActiveId(), friend.getPassiveId(), active.isProtect(), false);
            break;
        case LEAVE_FRIEND:
            friend = context.getFriend();
            active = directoryLogic.getUser(friend.getActiveId());
            shovelLogic.destroyFriendship(friend.getActiveId(), friend.getPassiveId(), active.isProtect(), false);
            break;
        default:
            throw new ApplicationException("");
        }
    }
    
    void updateStatus(IStatus status) throws ApplicationException {
        IDirectoryLogic directoryLogic = getDirectoryLogic();
        IShovelLogic shovelLogic = getShovelLogic();
        
        IStatusWrapper statusWrapper = shovelLogic.parseStatus(status.getBody());
        IUser sender = directoryLogic.getUser(status.getSenderId());
        String foreignKey = statusWrapper.getForeignKey();
        IUser user = null;
        if (foreignKey != null) {
            user = directoryLogic.getUserByForeignKey(foreignKey);
        }
        switch (statusWrapper.getStatusType()) {
        case STATUS:
            directoryLogic.incrementStatuses(sender.getUserId());
            long referenceSenderId = 0;
            if (user != null) {
                referenceSenderId = user.getUserId();
            }
            shovelLogic.updateStatus(statusWrapper.getText(), sender.getLocation(), source_,
                    referenceSenderId, statusWrapper.isOpen(), sender.getUserId(), false);
            break;
        case DIRECT_MESSAGE:
            directoryLogic.incrementDirectMessages(user.getUserId());
            shovelLogic.createDirectMessage(statusWrapper.getText(), source_,
                    sender.getUserId(), user.getUserId(), false);
            break;
        case FAVORITE:
            status = shovelLogic.getRecent(user.getUserId());
            if (status != null) {
                IFavorite favorite = shovelLogic.getFavorite(status.getStatusId(), sender.getUserId());
                if (favorite == null) {
                    directoryLogic.incrementFavorites(sender.getUserId());
                    if (user.getUserId() != sender.getUserId()) {
                        directoryLogic.incrementGivenFavorites(user.getUserId());
                    }
                    shovelLogic.createFavorite(status.getStatusId(), sender.getUserId(), false);
                }
            }
            break;
        case FOLLOW:
            shovelLogic.createFriendship(sender.getUserId(), user.getUserId(), sender.isProtect(), false);
            break;
        case LEAVE:
            shovelLogic.destroyFriendship(sender.getUserId(), user.getUserId(), sender.isProtect(), false);
            break;
        case NOTIFY_ON:
            shovelLogic.updateNotification(sender.getUserId(), user.getUserId(), true);
            break;
        case NOTIFY_OFF:
            shovelLogic.updateNotification(sender.getUserId(), user.getUserId(), false);
            break;
        case SLEEP:
            IDevice device = sender.getDevice();
            device.setAvailabilityType(OFF);
            shovelLogic.updateDevice(device);
            break;
        case WAKE:
            device = sender.getDevice();
            device.setAvailabilityType(ON);
            shovelLogic.updateDevice(device);
            break;
        default:
            break;
        }
    }
    
    /////
    
    S2Container container_;
    
    public void setContainer(S2Container container) {
        container_ = container;
    }
    S2Container getContainer() {
        return container_;
    }
    IDirectoryLogic getDirectoryLogic() {
        return (IDirectoryLogic)getContainer().getComponent(IDirectoryLogic.class);
    }
    IShovelLogic getShovelLogic() {
        return (IShovelLogic)getContainer().getComponent(IShovelLogic.class);
    }
}
