namespace SqlDynamite.Common

open System
open System.Data
open Neo4j.Driver

type Neo4jMetadataFinder() =
    inherit MetadataFinder()

    override this.Compose(tablename:string, fields:DataTable, keys:DataTable, checks:DataTable) : string =
        raise (NotImplementedException())

    override this.GetDefColumns(name:string, objtype:ObjectType) : DataTable list =
        [null; null; null]

    override this.GetTextColumns(name:string, objtype:ObjectType) : string list =
        let parts = this._connection.ConnectionString.Split(';')
        let url = parts.[0]
        let username = parts.[1]
        let password = parts.[2]
        let authToken = if (String.IsNullOrWhiteSpace(password) || String.IsNullOrWhiteSpace(username)) then AuthTokens.None else AuthTokens.Basic(username, password)

        let driver = GraphDatabase.Driver(url, authToken)
        let dbobjects = System.Collections.Generic.List<IRecord>()
        if   objtype = ObjectType.FUNCTION then
            dbobjects.AddRange(Neo4jConnection.GetData(driver, String.Format("SHOW FUNCTIONS
        YIELD name, signature AS desc
        WHERE name = '{0}'
        RETURN desc", name)))
        elif objtype = ObjectType.PROCEDURE then
            dbobjects.AddRange(Neo4jConnection.GetData(driver, String.Format("SHOW PROCEDURES
        YIELD name, signature AS desc
        WHERE name = '{0}'
        RETURN desc", name)))
        elif objtype = ObjectType.INDEX then    
            dbobjects.AddRange(Neo4jConnection.GetData(driver, String.Format("SHOW INDEXES
        YIELD name, createStatement AS desc
        WHERE name = '{0}'
        RETURN desc", name)))
        elif objtype = ObjectType.LABEL then    
            dbobjects.AddRange(Neo4jConnection.GetData(driver, String.Format("call db.labels()
        YIELD label AS desc
        WITH desc
        WHERE desc = '{0}'
        RETURN desc", name)))
        [String.Join(Environment.NewLine, [for dbobject in dbobjects do yield dbobject.Item("desc").ToString()])]

    override this.GetNameByTextColumns(searchStr:string, types:ObjectType list, caseSensitive:bool) : string =
        searchStr

    override this.GenerateNameScript(search:string, types:ObjectType list, caseSensitive:bool) : string =
        search

    override this.GenerateSearchScript(search:string, caseSensitive:bool) : string =
        search

    override this.GetForeignKeyDefinition(constraintName:string) : string =
        raise (NotImplementedException())

    override this.GetPrimaryKeyDefinition(constraintName:string) : string =
        raise (NotImplementedException())

    override this.GetIndexDefinition(constraintName:string) : string =
        this.GetTextColumns(constraintName, ObjectType.INDEX).Head

    override this.GetSequenceDefinition(sequenceName:string) : string =
        raise (NotImplementedException())

    override this.GetSynonymDefinition(synonymName:string) : string =
        raise (NotImplementedException())

    override this.GetTypeDefinition(typeName:string) : string =
        raise (NotImplementedException())

    override this.GetJobDefinition(jobName:string) : string =
        raise (NotImplementedException())

    override this.GetReportDefinition(reportName:string) : string =
        raise (NotImplementedException())

    override this.GetExtendedProcedureDefinition(procName:string) : string =
        raise (NotImplementedException())

    override this.GetExtendedTriggerDefinition(triggerName:string) : string =
        raise (NotImplementedException())
