package net.x4a42.volksempfaenger.data.entity.playlistitem;

import net.x4a42.volksempfaenger.data.entity.DaoWrapperBase;
import net.x4a42.volksempfaenger.data.entity.episode.Episode;

import java.util.List;

public class PlaylistItemDaoWrapper extends DaoWrapperBase<PlaylistItem>
{
    private final PlaylistItemProvider provider;

    public PlaylistItemDaoWrapper(PlaylistItemDao      playlistItemDao,
                                  PlaylistItemProvider provider)
    {
        super(playlistItemDao);
        this.provider = provider;
    }

    public PlaylistItem createPlaylistItem(Episode episode)
    {
        PlaylistItem playlistItem = provider.get();
        playlistItem.setEpisode(episode);
        playlistItem.setPosition(dao.count());
        super.insert(playlistItem);
        return playlistItem;
    }

    public List<PlaylistItem> getAll()
    {
        return dao.queryBuilder()
                  .orderAsc(PlaylistItemDao.Properties.Position)
                  .listLazy();
    }

    public PlaylistItem getByPosition(long position)
    {
        return dao.queryBuilder()
                  .where(PlaylistItemDao.Properties.Position.eq(position))
                  .list().get(0);
    }

    public boolean hasEpisode(Episode episode)
    {
        return !getListByEpisode(episode).isEmpty();
    }

    public PlaylistItem getByEpisode(Episode episode)
    {
        return getListByEpisode(episode).get(0);
    }

    public PlaylistItem getById(long playlistItemId)
    {
        return dao.queryBuilder()
                  .where(PlaylistItemDao.Properties._id.eq(playlistItemId))
                  .list().get(0);
    }

    @Override
    public void delete(PlaylistItem playlistItem)
    {
        long deletedPosition = playlistItem.getPosition();
        super.delete(playlistItem);

        for (PlaylistItem behindItem : getBehind(deletedPosition))
        {
            behindItem.setPosition(behindItem.getPosition() - 1);
            super.update(behindItem);
        }
    }

    @Override
    public long insert(PlaylistItem playlistItem)
    {
        throw new UnsupportedOperationException("use createPlaylistItem");
    }

    @Override
    public void update(PlaylistItem playlistItem)
    {
        throw new UnsupportedOperationException("use move");
    }

    public void moveToBack(PlaylistItem playlistItem)
    {
        long newPosition = dao.count();
        move(playlistItem, newPosition);
    }

    public void move(PlaylistItem playlistItem, long newPosition)
    {
        if (newPosition == playlistItem.getPosition())
        {
            return;
        }

        // TODO: wrap in transaction?
        if (newPosition < playlistItem.getPosition())
        {
            for (PlaylistItem rangeItem : getRange(playlistItem.getPosition() - 1, newPosition))
            {
                rangeItem.setPosition(rangeItem.getPosition() + 1);
                super.update(rangeItem);
            }
        }
        else
        {
            for (PlaylistItem rangeItem : getRange(playlistItem.getPosition() + 1, newPosition))
            {
                rangeItem.setPosition(rangeItem.getPosition() - 1);
                super.update(rangeItem);
            }
        }

        playlistItem.setPosition(newPosition);
        super.update(playlistItem);

    }

    private List<PlaylistItem> getRange(long from, long to)
    {
        if (to == -1)
        {
            return dao.queryBuilder()
                      .where(PlaylistItemDao.Properties.Position.ge(from))
                      .orderAsc(PlaylistItemDao.Properties.Position)
                      .listLazy();
        }
        else if (from == -1)
        {
            return dao.queryBuilder()
                    .where(PlaylistItemDao.Properties.Position.le(to))
                    .orderDesc(PlaylistItemDao.Properties.Position)
                    .listLazy();
        }
        if (from < to)
        {
            return dao.queryBuilder()
                      .where(PlaylistItemDao.Properties.Position.ge(from),
                             PlaylistItemDao.Properties.Position.le(to))
                      .orderAsc(PlaylistItemDao.Properties.Position)
                      .listLazy();
        }
        else
        {
            return dao.queryBuilder()
                      .where(PlaylistItemDao.Properties.Position.ge(to),
                             PlaylistItemDao.Properties.Position.le(from))
                      .orderDesc(PlaylistItemDao.Properties.Position)
                      .listLazy();
        }
    }

    private List<PlaylistItem> getBehind(long position)
    {
        return getRange(position + 1, -1);
    }

    private List<PlaylistItem> getInFront(long position)
    {
        return getRange(-1, position - 1);
    }

    private List<PlaylistItem> getListByEpisode(Episode episode)
    {
        return dao.queryBuilder()
                  .where(PlaylistItemDao.Properties.EpisodeId.eq(episode.get_id()))
                  .list();
    }

}

@@ -1911,22 +1911,14 @@
     
-behindItem.set
+update
 Posi
@@ -1922,16 +1922,28 @@
 osition(
+behindItem, 
 behindIt
@@ -1969,46 +1969,8 @@
 1);%0A
-            super.update(behindItem);%0A
     
@@ -2580,32 +2580,87 @@
 urn;%0A        %7D%0A%0A
+        long oldPosition = playlistItem.getPosition();%0A
         // TODO:
@@ -2689,31 +2689,30 @@
         
-if (new
+update
 Position
  %3C playl
@@ -2703,19 +2703,17 @@
 Position
- %3C 
+(
 playlist
@@ -2712,36 +2712,68 @@
 playlistItem
-.get
+, -1);%0A        if (newPosition %3C old
 Position
 ())%0A        
@@ -2752,34 +2752,32 @@
 on %3C oldPosition
-()
 )%0A        %7B%0A    
@@ -2827,32 +2827,19 @@
 nge(
-playlistItem.get
+old
 Position
 () -
@@ -2830,26 +2830,24 @@
 (oldPosition
-()
  - 1, newPos
@@ -2884,38 +2884,42 @@
         
-rangeItem.setPosition(
+updatePosition(rangeItem, 
 rangeIte
@@ -2944,49 +2944,8 @@
 1);%0A
-                super.update(rangeItem);%0A
     
@@ -3042,32 +3042,19 @@
 nge(
-playlistItem.get
+old
 Position
 () +
@@ -3049,19 +3049,16 @@
 Position
-() 
 + 1, new
@@ -3102,21 +3102,14 @@
     
-rangeItem.set
+update
 Posi
@@ -3105,32 +3105,43 @@
  updatePosition(
+rangeItem, 
 rangeItem.getPos
@@ -3169,62 +3169,161 @@
     
+ %7D%0A
      
-super.update(rangeItem
+   %7D%0A        updatePosition(playlistItem, newPosition
 );%0A    
+%7D%0A%0A
     
-    %7D%0A    
+private void updatePosition(PlaylistItem playlistItem, long newPosition)%0A
     
-%7D%0A
+%7B
 %0A   
@@ -3398,25 +3398,24 @@
 ylistItem);%0A
-%0A
     %7D%0A%0A    p

fix to move logic