package org.amc.game.chess;

import org.amc.game.chessserver.MoveEditor;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * Represents an immutable move in the game of chess
 * 
 * @author Adrian Mclaughlin
 *
 */
public class Move implements Serializable {
    
    private final Location start;
    private final Location end;
    public static final EmptyMove EMPTY_MOVE = new EmptyMove();
    public static final char MOVE_SEPARATOR = '-';

    public Move(Location start, Location end) {
        this.start = start;
        this.end = end;
    }

    public Move(String moveString) throws IllegalArgumentException {
        if(moveString.length() == 5) {
            this.start = new Location(moveString.substring(0,2));
            this.end = new Location(moveString.substring(3,5));
        } else {
            throw new IllegalArgumentException("Not a valid move string");
        }
    }
    
    /**
     * @return the start Location
     */
    public Location getStart() {
        return start;
    }

    /**
     * @return the end Location
     */
    public Location getEnd() {
        return end;
    }

    /**
     * The distance travelled in the X direction
     * 
     * @return Integer can be postive or negative
     */
    public Integer getDistanceX() {
        return end.getLetter().getIndex() - start.getLetter().getIndex();
    }

    /**
     * The distance travelled in the Y direction
     * 
     * @return Integer can be postive or negative
     */
    public Integer getDistanceY() {
        return end.getNumber() - start.getNumber();
    }

    /**
     * The distance travelled in the X direction
     * 
     * @return Integer is postive
     */
    public Integer getAbsoluteDistanceX() {
        return Math.abs(getDistanceX());
    }

    /**
     * The distance travelled in the Y direction
     * 
     * @return Integer is postive
     */
    public Integer getAbsoluteDistanceY() {
        return Math.abs(getDistanceY());
    }

    /**
     * @return String representation of the move
     */
    public String asString() {
        return start.asString() + MOVE_SEPARATOR + end.asString();
    }
    
    /**
     * @see Object#toString()
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append('[');
        sb.append(this.start);
        sb.append("-->");
        sb.append(this.end);
        sb.append(']');

        return sb.toString();
    }

    /**
     * Returns true if the movement is along a rank or file
     * 
     * @param move
     * @return boolean
     */
    public static boolean isFileOrRankMove(Move move) {
        return move.getAbsoluteDistanceX() == 0 && move.getAbsoluteDistanceY() > 0
                        || move.getAbsoluteDistanceX() > 0 && move.getAbsoluteDistanceY() == 0;
    }

    /**
     * Returns true if the movement is along a diagonal
     * 
     * @param move
     * @return boolean
     */
    public static boolean isDiagonalMove(Move move) {
        return move.getAbsoluteDistanceX().equals(move.getAbsoluteDistanceY())
                        && move.getAbsoluteDistanceX() > 0;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((end == null) ? 0 : end.hashCode());
        result = prime * result + ((start == null) ? 0 : start.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Move other = (Move) obj;
        return other.start.equals(start) && other.end.equals(end);
    }
    
    private Object writeReplace() {
        return new MoveSerializedProxy(this);
    }
    
    private void readObject(ObjectInputStream stream) throws InvalidObjectException {
        throw new InvalidObjectException("Proxy required");
    }
    
    private static class MoveSerializedProxy implements Serializable {
        private static final long serialVersionUID = 3118097389735009346L;
        private transient Location start;
        private transient Location end;
        
        public MoveSerializedProxy(Move move) {
            this.start = move.start;
            this.end = move.end;
        }
        
        private Object readResolve() {
            return new Move(start, end);
        }
        
        private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
            stream.defaultReadObject();
            String moveStr = stream.readUTF();
            MoveEditor e = new MoveEditor();
            e.setAsText(moveStr);
            Move m = (Move)e.getValue();
            this.start = m.start;
            this.end = m.end;
            
        }
        
        private void writeObject(ObjectOutputStream stream) throws IOException {
            stream.defaultWriteObject();
            MoveEditor e = new MoveEditor();
            e.setValue(new Move(start, end));
            stream.writeUTF(e.getAsText());
        }
    }
}

@@ -26,53 +26,8 @@
 s;%0A%0A
-import org.amc.game.chessserver.MoveEditor;%0A%0A
 impo
@@ -329,24 +329,91 @@
 zable %7B%0A    
+private static final long serialVersionUID = -7511044104434383204L;
 %0A    private
@@ -769,16 +769,17 @@
       if
+ 
 (moveStr
@@ -860,16 +860,17 @@
 tring(0,
+ 
 2));%0A   
@@ -925,16 +925,17 @@
 tring(3,
+ 
 5));%0A   
@@ -1035,28 +1035,24 @@
     %7D%0A    %7D%0A
-    
 %0A    /**%0A   
@@ -2279,28 +2279,24 @@
 ng();%0A    %7D%0A
-    
 %0A    /**%0A   
@@ -3880,36 +3880,32 @@
 als(end);%0A    %7D%0A
-    
 %0A    private Obj
@@ -3969,36 +3969,32 @@
 xy(this);%0A    %7D%0A
-    
 %0A    private voi
@@ -4130,20 +4130,16 @@
 ;%0A    %7D%0A
-    
 %0A    pri
@@ -4359,24 +4359,16 @@
 on end;%0A
-        
 %0A       
@@ -4484,32 +4484,24 @@
 ;%0A        %7D%0A
-        
 %0A        pri
@@ -4575,32 +4575,24 @@
 ;%0A        %7D%0A
-        
 %0A        pri
@@ -4657,16 +4657,40 @@
 ception,
+%0A                       
  ClassNo
@@ -4806,32 +4806,26 @@
         Move
-Editor e
+ m
  = new MoveE
@@ -4827,90 +4827,16 @@
 Move
-Editor();%0A            e.setAsText(moveStr);%0A            Move m = (Move)e.getValue(
+(moveStr
 );%0A 
@@ -4898,28 +4898,16 @@
  m.end;%0A
-            
 %0A       
@@ -4909,24 +4909,16 @@
       %7D%0A
-        
 %0A       
@@ -5048,126 +5048,53 @@
     
-MoveEditor e = new MoveEditor();%0A            e.setValue(new Move(start, end));%0A            stream.writeUTF(e.getAsText
+stream.writeUTF(new Move(start, end).asString
 ());

remove MoveEditor dependency