/*
    docfbe.cpp    June 6, 2004.

    Copyright (C) 2003-2004 CFbE Research Group,
    Software Engineering Laboratory,
    Graduate School of Information Science,
    Nara Institute of Science and Technology,
    All rights reserved.

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2, (at your option) or
    any later version.

    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with GNU Emacs; see the file COPYING.  If not, write to the
    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/
//---------------------------------------------------------------------------
#pragma hdrstop
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <SysUtils.hpp>
#include <stdio.h>

#include "EDocfbeError.h"
#include "TCFbEToolkit.h"
#include "TCFbEDocfbeCommandLineParser.h"
#include "TCFbEDocfbeDataLoader.h"
#include "TCFbEOutputCache.h"
#include "TCFbEOutputFormatter.h"
#include "TCFbECsvOutputFormatter.h"
#include "TCFbERecommendationOutputFormatter.h"

#include "TCFbEDataSetEx.h"
#include "TCFbESimilarityComputationAlgorithm.h"
#include "TCFbEPredictionAlgorithm.h"
//---------------------------------------------------------------------------
#pragma argsused
//---------------------------------------------------------------------------
//
int main(int argc, char* argv[])
{
    // コピーライト表示
    fprintf(stderr, "\n======================================================================\n");
    fprintf(stderr, "%s", TCFbEToolkit::GetToolkit()->GetCopyrightStr("Collaborative Filtering based Estimation (CFbE) Program"));
    fprintf(stderr, "======================================================================\n");
            
    try {         
        //------------------------------------------------------------
        // コマンドラインを解釈する
        TCFbEDocfbeCommandLineParser* Parser;
        try {
            Parser = new TCFbEDocfbeCommandLineParser(argc, argv);
        } catch (Exception& e) {
            throw EDocfbeError(-13, "Commandline Parsing", e.Message);
        }

        if (Parser->ErrorCode != 0) {    // エラーあり
            throw EDocfbeError(Parser->ErrorCode, Parser->ErrorParameter, "");
        }

        if (Parser->HelpEnabled) {    // ヘルプ表示
            fprintf(stderr, "%s", Parser->GetHelpString().c_str());

            // 終了処理
            TCFbEToolkit::DeleteToolkit();

            fprintf(stderr, "======================================================================\n");
            return 0;
        }

        fprintf(stderr, "CF based Estimation is started.\n\n");
        
        //------------------------------------------------------------
        // データを準備する
        TCFbEDocfbeDataLoader* DataLoader;
        try {  
            DataLoader = new TCFbEDocfbeDataLoader(Parser, true, 4, 1);
        } catch (Exception &e) {
            delete Parser;
            throw EDocfbeError(-13, "Data Loading", e.Message);
        }

        if (DataLoader->ErrorCode != 0) {    // エラーあり
            throw EDocfbeError(DataLoader->ErrorCode, DataLoader->ErrorParameter, "");
        }

        //------------------------------------------------------------
        // 協調フィルタリングを行い，対象メトリクスを予測する
        TCFbEOutputCache* OutputCache;
        try {
            OutputCache = new TCFbEOutputCache(Parser, DataLoader, true);
        } catch (Exception &e) {
            delete Parser;
            delete DataLoader;
            throw EDocfbeError(-13, "Estimating", e.Message);
        }           

        //------------------------------------------------------------
        // 予測結果をファイル，若しくは，標準出力に書き出す
        TCFbEOutputFormatter*    Formatter;
        try {
            if (Parser->Recommendation) {
                Formatter = new TCFbERecommendationOutputFormatter(Parser, OutputCache, true);
            } else {
                Formatter = new TCFbECsvOutputFormatter(Parser, OutputCache, true);
            }            
        } catch (Exception &e) {
            delete OutputCache;
            delete Parser;
            delete DataLoader;
            throw EDocfbeError(-13, "Output Formatting", e.Message);
        }


        if (Parser->OutputFileName.IsEmpty()) {    // 標準出力に出力
            fprintf(stdout, "%s\n", Formatter->GetOutputString().c_str());

        } else {    // ファイルに保存
            try {
                Formatter->SaveOutputStringTo(Parser->OutputFileName);
            } catch (EFCreateError &efce) {
                throw EDocfbeError(-12, Parser->OutputFileName, efce.Message);
            }
        }

        delete Formatter;
        delete OutputCache;
        delete Parser;
        delete DataLoader;

        fprintf(stderr, "CF based Estimation is successfully completed.\n");

    } catch (EDocfbeError &ede) {    // 異常終了例外を受け取る catch
        fprintf(stderr, "\n\nCF based Estimation terminated unsuccessfully with the following error.");
        fprintf(stderr, "\n\nError Code %d: %s\n\n", ede.ErrorCode, ede.Message);
        fprintf(stderr, "======================================================================\n");
        return ede.ErrorCode;
        
    } catch (...) {
        throw;
    }

    // 終了処理
    TCFbEToolkit::DeleteToolkit();

    fprintf(stderr, "======================================================================\n");
    
    return 0;
}

//---------------------------------------------------------------------------
