/**
 * IgoNewModel クラスは、新規作成モードのモデルを提供します。
 * @author Jiro Suzuki
 */
public class IgoNewModel extends IgoModel{

    private Kifu kifuForRecord;
    private int numForRecord;

    /**
     * 指定された親インスタンスに対するインスタンスを生成します。
     * @param parent 親インスタンス
     */
    IgoNewModel(IgoModel parent){
        this.parent=parent;
    }

    /**
     * インスタンスを初期化します。
     * @param view ビュー
     */
    public void initialize(IgoView view){
        super.initialize(view);
        kifuForRecord=new Kifu();
        numForRecord=-1;    
    }

    /**
     * 棋譜情報を、名前を付けて保存します。
     */
    public void saveAs(){
        String fileName=view.showSaveDialog();
        if(fileName.length()!=0){
            this.fileName=fileName;
            write();
            IgoModModel modModel=new IgoModModel(parent);
            modModel.initialize(view);
            view.changeController(modModel);
            modModel.start(kifu,numOfMoves,fileName,turn);
        }
    }

    /**
      * 現行モードを終了するときに呼び出します。
      */
    public void exit(){
        switch(view.askClosedOperation()){
            case NotSaveAndNotClose:
                break;
            case NotSaveAndClose:
                System.exit(0);
                break;
            case SaveAndClose:
                String fileName=view.showSaveDialog();
                if(fileName.length()!=0){
                    this.fileName=fileName;
                    write();
                    System.exit(0);
                    break;
                }
                break;
        }
    }

    /**
      * メインダイアログを閉じるときに呼び出します。
      */
    public void close(){
        switch(view.askClosedOperation()){
            case NotSaveAndNotClose:
                break;
            case NotSaveAndClose:
                view.changeController(parent);
                parent.start();
                break;
            case SaveAndClose:
                String fileName=view.showSaveDialog();
                if(fileName.length()!=0){
                    this.fileName=fileName;
                    write();
                    view.changeController(parent);
                    parent.start();
                    break;
                }
        }
    }

    /**
      * 一手戻るときに呼び出します。
      */
    public void back(){ 
        if(numOfMoves>0){
            numOfMoves--;
            intBoard.initialize();
            for(int i=0;i<=numOfMoves;i++){
                Move move=kifu.getOrderOfMoves().getMove(i);
                intBoard.update(move.getStoneColor(),move.getRow(),move.getCol());
            }
            turn.setTurn(kifu.getOrderOfMoves().getMove(numOfMoves).getStoneColor());
            turn.changeTurn();
        }else if(numOfMoves==0){
            numOfMoves--;
            intBoard.initialize();
            turn.setTurn(Turn.TURN_BLACK);
        }
        view.updateView(mode,isExam,intBoard,kifu.getGameInformation(),numOfMoves);
    }

    /**
      * 一手進むときに呼び出します。
      */
    public void forward(){
        OrderOfMoves order=kifu.getOrderOfMoves();
        if(numOfMoves<order.size()-1){
            numOfMoves++;
            Move move=order.getMove(numOfMoves);
            intBoard.update(move.getStoneColor(),move.getRow(),move.getCol());
            turn.setTurn(move.getStoneColor());
            turn.changeTurn();
            view.updateView(mode,isExam,intBoard,kifu.getGameInformation(),numOfMoves);
        }
    }

    /**
      * 五手戻るときに呼び出します。
      */
    public void back5(){
        intBoard.initialize();
        if(numOfMoves>4){
            numOfMoves=numOfMoves-5;
            for(int i=0;i<=numOfMoves;i++){
                Move move=kifu.getOrderOfMoves().getMove(i);
                intBoard.update(move.getStoneColor(),move.getRow(),move.getCol());
            }
            turn.setTurn(kifu.getOrderOfMoves().getMove(numOfMoves).getStoneColor());
            turn.changeTurn();
        }else{
            numOfMoves=-1;
            turn.setTurn(Turn.TURN_BLACK);
        }
        view.updateView(mode,isExam,intBoard,kifu.getGameInformation(),numOfMoves);
    }

    /**
      * 五手進むときに呼び出します。
      */
    public void forward5(){
        numOfMoves=numOfMoves+5;
        OrderOfMoves order=kifu.getOrderOfMoves();
        if(numOfMoves>order.size()-1){
            numOfMoves=order.size()-1;
        }
        intBoard.initialize();
        for(int i=0;i<=numOfMoves;i++){
            Move move=order.getMove(i);
            intBoard.update(move.getStoneColor(),move.getRow(),move.getCol());
        }

        if(numOfMoves>-1){
            turn.setTurn(kifu.getOrderOfMoves().getMove(numOfMoves).getStoneColor());
            turn.changeTurn();
        }else{
            turn.setTurn(Turn.TURN_BLACK);
        }

        view.updateView(mode,isExam,intBoard,kifu.getGameInformation(),numOfMoves);
    }

    /**
      * 初手に戻るときに呼び出します。
      */
    public void backAll(){ 
        numOfMoves=-1;
        turn.setTurn(Turn.TURN_BLACK);
        intBoard.initialize();
        view.updateView(mode,isExam,intBoard,kifu.getGameInformation(),numOfMoves);
    }

    /**
      * 終局面にするときに呼び出します。
      */
    public void forwardAll(){
        OrderOfMoves order=kifu.getOrderOfMoves();
        numOfMoves=order.size()-1;
        intBoard.initialize();
        for(int i=0;i<=numOfMoves;i++){
            Move move=order.getMove(i);
            intBoard.update(move.getStoneColor(),move.getRow(),move.getCol());
        }

        if(numOfMoves>-1){
            turn.setTurn(kifu.getOrderOfMoves().getMove(numOfMoves).getStoneColor());
            turn.changeTurn();
        }else{
            turn.setTurn(Turn.TURN_BLACK);
        }

        view.updateView(mode,isExam,intBoard,kifu.getGameInformation(),numOfMoves);
    }

    /**
      * パスをするときに呼び出します。
      */
    public void pass(){
        turn.changeTurn();
    }

    /**
      * 設計途中で変更が生じたため、棚上げ。
      */
    public void pause(){}

    /**
      * 検討モードと再生モードを行き来するときに呼び出します。
      */
    public void examine(){
        if(isExam){
            isExam=false;
            intBoard.initialize();
            kifu=kifuForRecord;
            numOfMoves=numForRecord;
            for(int i=0;i<=numOfMoves;i++){
                Move move=kifu.getOrderOfMoves().getMove(i);
                intBoard.update(move.getStoneColor(),move.getRow(),move.getCol());
            }

            if(numOfMoves>-1){
                turn.setTurn(kifu.getOrderOfMoves().getMove(numOfMoves).getStoneColor());
                turn.changeTurn();
            }else{
                turn.setTurn(Turn.TURN_BLACK);
            }

            view.updateView(mode,isExam,intBoard,kifu.getGameInformation(),numOfMoves);

        }else{
            kifuForRecord=kifu;
            kifuForExam=kifu.createExamClone(numOfMoves);
            kifu=kifuForExam;
            numForRecord=numOfMoves;
            isExam=true;
            view.updateView(mode,isExam,intBoard,kifu.getGameInformation(),numOfMoves);
        }
    }

    /**
     * 石を置くときに呼び出します。
     * @param row 行番号
     * @param col 列番号
     */
    public void putStone(int row,int col){
        OrderOfMoves order=kifu.getOrderOfMoves();
        if((intBoard.getIntBoard())[row][col]==0){
            for(int i=order.size()-1;i>numOfMoves;i--){
                order.remove(i);
            }
            kifu.addMove(new Move(turn.getTurn(),row,col));
            numOfMoves++;
            turn.changeTurn();
            Move move=kifu.getOrderOfMoves().getMove(numOfMoves);
            intBoard.update(move.getStoneColor(),move.getRow(),move.getCol());
            view.updateView(mode,isExam,intBoard,kifu.getGameInformation(),numOfMoves);
        }
    }

    /**
      * 対局情報を更新するときに呼び出します。
      */
    public void updateGameInfo(GameInformation gameInfo){
        kifu.getGameInformation().setBlackPlayer(gameInfo.getBlackPlayer());
        kifu.getGameInformation().setWhitePlayer(gameInfo.getWhitePlayer());
        kifu.getGameInformation().setBlackRank(gameInfo.getBlackRank());
        kifu.getGameInformation().setWhiteRank(gameInfo.getWhiteRank());
        kifu.getGameInformation().setEvent(gameInfo.getEvent());
        kifu.getGameInformation().setGameName(gameInfo.getGameName());
        kifu.getGameInformation().setDate(gameInfo.getDate());
        kifu.getGameInformation().setKomi(gameInfo.getKomi());
        kifu.getGameInformation().setResult(gameInfo.getResult());
        view.updateView(mode,isExam,intBoard,kifu.getGameInformation(),numOfMoves);
    }

    /**
      * 新規作成モードを開始するときに呼び出します。
      */
    public void start(){
        initialize();
        mode.setMode(Mode.MODE_NEW);
        view.updateView(mode,isExam,intBoard,kifu.getGameInformation(),numOfMoves);
    }

    /**
      * 対局情報を表示ときに呼び出します。
      */
    public void displayGameInfo(){
        view.showGameInfoDialog(kifu.getGameInformation());
    }

    /**
      * ビューを更新するときに呼び出します。
      */
    public void doUpdateView(){
        view.updateView(mode,isExam,intBoard,kifu.getGameInformation(),numOfMoves);
    }

    //------------------------------------------------------------------------
    private void write(){
        SgfWriter writer=new SgfWriter();
        writer.write(fileName,kifu);
    }
}