/*
 * Copyright (C) 2008 Esmertec AG.
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed 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 com.android.mms.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.smil.ElementTime;

import android.text.TextUtils;
import android.util.Config;
import android.util.Log;

import com.android.mms.ContentRestrictionException;
import com.android.mms.dom.smil.SmilParElementImpl;
import com.google.android.mms.ContentType;

public class SlideModel extends Model implements List<MediaModel>, EventListener {
    public static final String TAG = "Mms/slideshow";
    private static final boolean DEBUG = false;
    private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
    private static final int DEFAULT_SLIDE_DURATION = 5000;

    private final ArrayList<MediaModel> mMedia = new ArrayList<MediaModel>();

    private MediaModel mText;
    private MediaModel mImage;
    private MediaModel mAudio;
    private MediaModel mVideo;

    private boolean mCanAddImage = true;
    private boolean mCanAddAudio = true;
    private boolean mCanAddVideo = true;

    private int mDuration;
    private boolean mVisible = true;
    private short mFill;
    private int mSlideSize;
    private SlideshowModel mParent;

    public SlideModel(SlideshowModel slideshow) {
        this(DEFAULT_SLIDE_DURATION, slideshow);
    }

    public SlideModel(int duration, SlideshowModel slideshow) {
        mDuration = duration;
        mParent = slideshow;
    }

    /**
     * Create a SlideModel with exist media collection.
     *
     * @param duration The duration of the slide.
     * @param mediaList The exist media collection.
     *
     * @throws IllegalStateException One or more media in the mediaList cannot
     *         be added into the slide due to a slide cannot contain image
     *         and video or audio and video at the same time.
     */
    public SlideModel(int duration, ArrayList<MediaModel> mediaList) {
        mDuration = duration;

        int maxDur = 0;
        for (MediaModel media : mediaList) {
            internalAdd(media);

            int mediaDur = media.getDuration();
            if (mediaDur > maxDur) {
                maxDur = mediaDur;
            }
        }

        updateDuration(maxDur);
    }

    private void internalAdd(MediaModel media) throws IllegalStateException {
        if (media == null) {
            // Don't add null value into the list.
            return;
        }

        if (media.isText()) {
            String contentType = media.getContentType();
            if (TextUtils.isEmpty(contentType) || ContentType.TEXT_PLAIN.equals(contentType)
                    || ContentType.TEXT_HTML.equals(contentType)) {
                internalAddOrReplace(mText, media);
                mText = media;
            } else {
                Log.w(TAG, "[SlideModel] content type " + media.getContentType() +
                        " isn't supported (as text)");
            }
        } else if (media.isImage()) {
            if (mCanAddImage) {
                internalAddOrReplace(mImage, media);
                mImage = media;
                mCanAddVideo = false;
            } else {
                Log.w(TAG, "[SlideModel] content type " + media.getContentType() +
                    " - can't add image in this state");
            }
        } else if (media.isAudio()) {
            if (mCanAddAudio) {
                internalAddOrReplace(mAudio, media);
                mAudio = media;
                mCanAddVideo = false;
            } else {
                Log.w(TAG, "[SlideModel] content type " + media.getContentType() +
                    " - can't add audio in this state");
            }
        } else if (media.isVideo()) {
            if (mCanAddVideo) {
                internalAddOrReplace(mVideo, media);
                mVideo = media;
                mCanAddImage = false;
                mCanAddAudio = false;
            } else {
                Log.w(TAG, "[SlideModel] content type " + media.getContentType() +
                    " - can't add video in this state");
            }
        }
    }

    private void internalAddOrReplace(MediaModel old, MediaModel media) {
        // If the media is resizable, at this point consider it to be zero length.
        // Just before we send the slideshow, we take the remaining space in the
        // slideshow and equally allocate it to all the resizeable media items and resize them.
        int addSize = media.getMediaResizable() ? 0 : media.getMediaSize();
        int removeSize;
        if (old == null) {
            if (null != mParent) {
                mParent.checkMessageSize(addSize);
            }
            mMedia.add(media);
            increaseSlideSize(addSize);
            increaseMessageSize(addSize);
        } else {
            removeSize = old.getMediaResizable() ? 0 : old.getMediaSize();
            if (addSize > removeSize) {
                if (null != mParent) {
                    mParent.checkMessageSize(addSize - removeSize);
                }
                increaseSlideSize(addSize - removeSize);
                increaseMessageSize(addSize - removeSize);
            } else {
                decreaseSlideSize(removeSize - addSize);
                decreaseMessageSize(removeSize - addSize);
            }
            mMedia.set(mMedia.indexOf(old), media);
            old.unregisterAllModelChangedObservers();
        }

        for (IModelChangedObserver observer : mModelChangedObservers) {
            media.registerModelChangedObserver(observer);
        }
    }

    private boolean internalRemove(Object object) {
        if (mMedia.remove(object)) {
            if (object instanceof TextModel) {
                mText = null;
            } else if (object instanceof ImageModel) {
                mImage = null;
                mCanAddVideo = true;
            } else if (object instanceof AudioModel) {
                mAudio = null;
                mCanAddVideo = true;
            } else if (object instanceof VideoModel) {
                mVideo = null;
                mCanAddImage = true;
                mCanAddAudio = true;
            }
            // If the media is resizable, at this point consider it to be zero length.
            // Just before we send the slideshow, we take the remaining space in the
            // slideshow and equally allocate it to all the resizeable media items and resize them.
            int decreaseSize = ((MediaModel) object).getMediaResizable() ? 0
                                        : ((MediaModel) object).getMediaSize();
            decreaseSlideSize(decreaseSize);
            decreaseMessageSize(decreaseSize);

            ((Model) object).unregisterAllModelChangedObservers();

            return true;
        }

        return false;
    }

    /**
     * @return the mDuration
     */
    public int getDuration() {
        return mDuration;
    }

    /**
     * @param duration the mDuration to set
     */
    public void setDuration(int duration) {
        mDuration = duration;
        notifyModelChanged(true);
    }

    public int getSlideSize() {
        return mSlideSize;
    }

    public void increaseSlideSize(int increaseSize) {
        if (increaseSize > 0) {
            mSlideSize += increaseSize;
        }
    }

    public void decreaseSlideSize(int decreaseSize) {
        if (decreaseSize > 0) {
            mSlideSize -= decreaseSize;
            if (mSlideSize < 0) {
                mSlideSize = 0;
            }
        }
    }

    public void setParent(SlideshowModel parent) {
        mParent = parent;
    }

    public void increaseMessageSize(int increaseSize) {
        if ((increaseSize > 0) && (null != mParent)) {
            int size = mParent.getCurrentMessageSize();
            size += increaseSize;
            mParent.setCurrentMessageSize(size);
        }
    }

    public void decreaseMessageSize(int decreaseSize) {
        if ((decreaseSize > 0) && (null != mParent)) {
            int size = mParent.getCurrentMessageSize();
            size -= decreaseSize;
            if (size < 0) {
                size = 0;
            }
            mParent.setCurrentMessageSize(size);
        }
    }

    //
    // Implement List<E> interface.
    //

    /**
     * Add a MediaModel to the slide. If the slide has already contained
     * a media object in the same type, the media object will be replaced by
     * the new one.
     *
     * @param object A media object to be added into the slide.
     * @return true
     * @throws IllegalStateException One or more media in the mediaList cannot
     *         be added into the slide due to a slide cannot contain image
     *         and video or audio and video at the same time.
     * @throws ContentRestrictionException when can not add this object.
     *
     */
    public boolean add(MediaModel object) {
        internalAdd(object);
        notifyModelChanged(true);
        return true;
    }

    public boolean addAll(Collection<? extends MediaModel> collection) {
        throw new UnsupportedOperationException("Operation not supported.");
    }

    public void clear() {
        if (mMedia.size() > 0) {
            for (MediaModel media : mMedia) {
                media.unregisterAllModelChangedObservers();
                int decreaseSize = media.getMediaSize();
                decreaseSlideSize(decreaseSize);
                decreaseMessageSize(decreaseSize);
            }
            mMedia.clear();

            mText = null;
            mImage = null;
            mAudio = null;
            mVideo = null;

            mCanAddImage = true;
            mCanAddAudio = true;
            mCanAddVideo = true;

            notifyModelChanged(true);
        }
    }

    public boolean contains(Object object) {
        return mMedia.contains(object);
    }

    public boolean containsAll(Collection<?> collection) {
        return mMedia.containsAll(collection);
    }

    public boolean isEmpty() {
        return mMedia.isEmpty();
    }

    public Iterator<MediaModel> iterator() {
        return mMedia.iterator();
    }

    public boolean remove(Object object) {
        if ((object != null) && (object instanceof MediaModel)
                && internalRemove(object)) {
            notifyModelChanged(true);
            return true;
        }
        return false;
    }

    public boolean removeAll(Collection<?> collection) {
        throw new UnsupportedOperationException("Operation not supported.");
    }

    public boolean retainAll(Collection<?> collection) {
        throw new UnsupportedOperationException("Operation not supported.");
    }

    public int size() {
        return mMedia.size();
    }

    public Object[] toArray() {
        return mMedia.toArray();
    }

    public <T> T[] toArray(T[] array) {
        return mMedia.toArray(array);
    }

    public void add(int location, MediaModel object) {
        throw new UnsupportedOperationException("Operation not supported.");
    }

    public boolean addAll(int location,
            Collection<? extends MediaModel> collection) {
        throw new UnsupportedOperationException("Operation not supported.");
    }

    public MediaModel get(int location) {
        if (mMedia.size() == 0) {
            return null;
        }

        return mMedia.get(location);
    }

    public int indexOf(Object object) {
        return mMedia.indexOf(object);
    }

    public int lastIndexOf(Object object) {
        return mMedia.lastIndexOf(object);
    }

    public ListIterator<MediaModel> listIterator() {
        return mMedia.listIterator();
    }

    public ListIterator<MediaModel> listIterator(int location) {
        return mMedia.listIterator(location);
    }

    public MediaModel remove(int location) {
        MediaModel media = mMedia.get(location);
        if ((media != null) && internalRemove(media)) {
            notifyModelChanged(true);
        }
        return media;
    }

    public MediaModel set(int location, MediaModel object) {
        throw new UnsupportedOperationException("Operation not supported.");
    }

    public List<MediaModel> subList(int start, int end) {
        return mMedia.subList(start, end);
    }

    /**
     * @return the mVisible
     */
    public boolean isVisible() {
        return mVisible;
    }

    /**
     * @param visible the mVisible to set
     */
    public void setVisible(boolean visible) {
        mVisible = visible;
        notifyModelChanged(true);
    }

    /**
     * @return the mFill
     */
    public short getFill() {
        return mFill;
    }

    /**
     * @param fill the mFill to set
     */
    public void setFill(short fill) {
        mFill = fill;
        notifyModelChanged(true);
    }

    @Override
    protected void registerModelChangedObserverInDescendants(
            IModelChangedObserver observer) {
        for (MediaModel media : mMedia) {
            media.registerModelChangedObserver(observer);
        }
    }

    @Override
    protected void unregisterModelChangedObserverInDescendants(
            IModelChangedObserver observer) {
        for (MediaModel media : mMedia) {
            media.unregisterModelChangedObserver(observer);
        }
    }

    @Override
    protected void unregisterAllModelChangedObserversInDescendants() {
        for (MediaModel media : mMedia) {
            media.unregisterAllModelChangedObservers();
        }
    }

    // EventListener Interface
    public void handleEvent(Event evt) {
        if (evt.getType().equals(SmilParElementImpl.SMIL_SLIDE_START_EVENT)) {
            if (LOCAL_LOGV) {
                Log.v(TAG, "Start to play slide: " + this);
            }
            mVisible = true;
        } else if (mFill != ElementTime.FILL_FREEZE) {
            if (LOCAL_LOGV) {
                Log.v(TAG, "Stop playing slide: " + this);
            }
            mVisible = false;
        }

        notifyModelChanged(false);
    }

    public boolean hasText() {
        return mText != null;
    }

    public boolean hasImage() {
        return mImage != null;
    }

    public boolean hasAudio() {
        return mAudio != null;
    }

    public boolean hasVideo() {
        return mVideo != null;
    }

    public boolean removeText() {
        return remove(mText);
    }

    public boolean removeImage() {
        return remove(mImage);
    }

    public boolean removeAudio() {
        boolean result = remove(mAudio);
        resetDuration();
        return result;
    }

    public boolean removeVideo() {
        boolean result = remove(mVideo);
        resetDuration();
        return result;
    }

    public TextModel getText() {
        return (TextModel) mText;
    }

    public ImageModel getImage() {
        return (ImageModel) mImage;
    }

    public AudioModel getAudio() {
        return (AudioModel) mAudio;
    }

    public VideoModel getVideo() {
        return (VideoModel) mVideo;
    }

    public void resetDuration() {
        // If we remove all the objects that have duration, reset the slide back to its
        // default duration. If we don't do this, if the user replaces a 10 sec video with
        // a 3 sec audio, the duration will remain at 10 sec (see the way updateDuration() below
        // works).
        if (!hasAudio() && !hasVideo()) {
            mDuration = DEFAULT_SLIDE_DURATION;
        }
    }

    public void updateDuration(int duration) {
        if (duration <= 0) {
            return;
        }

        if ((duration > mDuration)
                || (mDuration == DEFAULT_SLIDE_DURATION)) {
            mDuration = duration;
        }
    }
}
