package defaults

import (
	"os"
	"path"

	"github.com/owncloud/ocis/ocis-pkg/config/defaults"
	"github.com/owncloud/ocis/storage/pkg/config"
)

const (
	defaultPublicURL        = "https://localhost:9200"
	defaultShareFolder      = "/Shares"
	defaultStorageNamespace = "/users/{{.Id.OpaqueId}}"
	defaultGatewayAddr      = "127.0.0.1:9142"
	defaultUserLayout       = "{{.Id.OpaqueId}}"
)

func FullDefaultConfig() *config.Config {
	cfg := DefaultConfig()

	EnsureDefaults(cfg)
	Sanitize(cfg)

	return cfg
}

func DefaultConfig() *config.Config {
	return &config.Config{
		// log is inherited
		Debug: config.Debug{
			Addr: "127.0.0.1:9109",
		},
		Reva: config.Reva{
			JWTSecret:             "Pive-Fumkiu4",
			SkipUserGroupsInToken: false,
			TransferSecret:        "replace-me-with-a-transfer-secret",
			TransferExpires:       24 * 60 * 60,
			OIDC: config.OIDC{
				Issuer:   defaultPublicURL,
				Insecure: false,
				IDClaim:  "preferred_username",
			},
			LDAP: config.LDAP{
				Hostname:             "localhost",
				Port:                 9126,
				CACert:               path.Join(defaults.BaseDataPath(), "ldap", "ldap.crt"),
				Insecure:             false,
				BaseDN:               "dc=ocis,dc=test",
				LoginFilter:          "(&(objectclass=posixAccount)(|(cn={{login}})(mail={{login}})))",
				UserFilter:           "(&(objectclass=posixAccount)(|(ownclouduuid={{.OpaqueId}})(cn={{.OpaqueId}})))",
				UserAttributeFilter:  "(&(objectclass=posixAccount)({{attr}}={{value}}))",
				UserFindFilter:       "(&(objectclass=posixAccount)(|(cn={{query}}*)(displayname={{query}}*)(mail={{query}}*)))",
				UserGroupFilter:      "(&(objectclass=posixGroup)(cn={{query}}*))",
				GroupFilter:          "(&(objectclass=posixGroup)(|(ownclouduuid={{.OpaqueId}})(cn={{.OpaqueId}})))",
				GroupAttributeFilter: "(&(objectclass=posixGroup)({{attr}}={{value}}))",
				GroupFindFilter:      "(&(objectclass=posixGroup)(|(cn={{query}}*)(displayname={{query}}*)(mail={{query}}*)))",
				GroupMemberFilter:    "(&(objectclass=posixAccount)(ownclouduuid={{.OpaqueId}}*))",
				BindDN:               "cn=reva,ou=sysusers,dc=ocis,dc=test",
				BindPassword:         "reva",
				IDP:                  defaultPublicURL,
				UserSchema: config.LDAPUserSchema{
					UID:         "ownclouduuid",
					Mail:        "mail",
					DisplayName: "displayname",
					CN:          "cn",
					UIDNumber:   "uidnumber",
					GIDNumber:   "gidnumber",
				},
				GroupSchema: config.LDAPGroupSchema{
					GID:         "cn",
					Mail:        "mail",
					DisplayName: "cn",
					CN:          "cn",
					GIDNumber:   "gidnumber",
				},
			},
			UserGroupRest: config.UserGroupRest{
				RedisAddress: "localhost:6379",
			},
			UserOwnCloudSQL: config.UserOwnCloudSQL{
				DBUsername:         "owncloud",
				DBPassword:         "secret",
				DBHost:             "mysql",
				DBPort:             3306,
				DBName:             "owncloud",
				Idp:                defaultPublicURL,
				Nobody:             90,
				JoinUsername:       false,
				JoinOwnCloudUUID:   false,
				EnableMedialSearch: false,
			},
			OCDav: config.OCDav{
				WebdavNamespace:   defaultStorageNamespace,
				DavFilesNamespace: defaultStorageNamespace,
			},
			Archiver: config.Archiver{
				MaxNumFiles: 10000,
				MaxSize:     1073741824,
				ArchiverURL: "/archiver",
			},
			UserStorage: config.StorageConfig{
				EOS: config.DriverEOS{
					DriverCommon: config.DriverCommon{
						Root:        "/eos/dockertest/reva",
						ShareFolder: defaultShareFolder,
						UserLayout:  "{{substr 0 1 .Username}}/{{.Username}}",
					},
					ShadowNamespace:  "", // Defaults to path.Join(c.Namespace, ".shadow")
					UploadsNamespace: "", // Defaults to path.Join(c.Namespace, ".uploads")
					EosBinary:        "/usr/bin/eos",
					XrdcopyBinary:    "/usr/bin/xrdcopy",
					MasterURL:        "root://eos-mgm1.eoscluster.cern.ch:1094",
					SlaveURL:         "root://eos-mgm1.eoscluster.cern.ch:1094",
					CacheDirectory:   os.TempDir(),
					GatewaySVC:       defaultGatewayAddr,
				},
				Local: config.DriverCommon{
					Root:        path.Join(defaults.BaseDataPath(), "storage", "local", "users"),
					ShareFolder: defaultShareFolder,
					UserLayout:  "{{.Username}}",
					EnableHome:  false,
				},
				OwnCloudSQL: config.DriverOwnCloudSQL{
					DriverCommon: config.DriverCommon{
						Root:        path.Join(defaults.BaseDataPath(), "storage", "owncloud"),
						ShareFolder: defaultShareFolder,
						UserLayout:  "{{.Username}}",
						EnableHome:  false,
					},
					UploadInfoDir: path.Join(defaults.BaseDataPath(), "storage", "uploadinfo"),
					DBUsername:    "owncloud",
					DBPassword:    "owncloud",
					DBHost:        "",
					DBPort:        3306,
					DBName:        "owncloud",
				},
				S3: config.DriverS3{
					DriverCommon: config.DriverCommon{},
					Region:       "default",
					AccessKey:    "",
					SecretKey:    "",
					Endpoint:     "",
					Bucket:       "",
				},
				S3NG: config.DriverS3NG{
					DriverCommon: config.DriverCommon{
						Root:        path.Join(defaults.BaseDataPath(), "storage", "users"),
						ShareFolder: defaultShareFolder,
						UserLayout:  defaultUserLayout,
						EnableHome:  false,
					},
					Region:    "default",
					AccessKey: "",
					SecretKey: "",
					Endpoint:  "",
					Bucket:    "",
				},
				OCIS: config.DriverOCIS{
					DriverCommon: config.DriverCommon{
						Root:        path.Join(defaults.BaseDataPath(), "storage", "users"),
						ShareFolder: defaultShareFolder,
						UserLayout:  defaultUserLayout,
					},
				},
			},
			MetadataStorage: config.StorageConfig{
				EOS: config.DriverEOS{
					DriverCommon: config.DriverCommon{
						Root:        "/eos/dockertest/reva",
						ShareFolder: defaultShareFolder,
						UserLayout:  "{{substr 0 1 .Username}}/{{.Username}}",
						EnableHome:  false,
					},
					ShadowNamespace:     "",
					UploadsNamespace:    "",
					EosBinary:           "/usr/bin/eos",
					XrdcopyBinary:       "/usr/bin/xrdcopy",
					MasterURL:           "root://eos-mgm1.eoscluster.cern.ch:1094",
					GrpcURI:             "",
					SlaveURL:            "root://eos-mgm1.eoscluster.cern.ch:1094",
					CacheDirectory:      os.TempDir(),
					EnableLogging:       false,
					ShowHiddenSysFiles:  false,
					ForceSingleUserMode: false,
					UseKeytab:           false,
					SecProtocol:         "",
					Keytab:              "",
					SingleUsername:      "",
					GatewaySVC:          defaultGatewayAddr,
				},
				Local: config.DriverCommon{
					Root: path.Join(defaults.BaseDataPath(), "storage", "local", "metadata"),
				},
				OwnCloudSQL: config.DriverOwnCloudSQL{},
				S3: config.DriverS3{
					DriverCommon: config.DriverCommon{},
					Region:       "default",
				},
				S3NG: config.DriverS3NG{
					DriverCommon: config.DriverCommon{
						Root:        path.Join(defaults.BaseDataPath(), "storage", "metadata"),
						ShareFolder: "",
						UserLayout:  defaultUserLayout,
						EnableHome:  false,
					},
					Region:    "default",
					AccessKey: "",
					SecretKey: "",
					Endpoint:  "",
					Bucket:    "",
				},
				OCIS: config.DriverOCIS{
					DriverCommon: config.DriverCommon{
						Root:        path.Join(defaults.BaseDataPath(), "storage", "metadata"),
						ShareFolder: "",
						UserLayout:  defaultUserLayout,
						EnableHome:  false,
					},
				},
			},
			Frontend: config.FrontendPort{
				Port: config.Port{
					MaxCPUs:     "",
					LogLevel:    "",
					GRPCNetwork: "",
					GRPCAddr:    "",
					HTTPNetwork: "tcp",
					HTTPAddr:    "127.0.0.1:9140",
					Protocol:    "",
					Endpoint:    "",
					DebugAddr:   "127.0.0.1:9141",
					Services:    []string{"datagateway", "ocdav", "ocs", "appprovider"},
					Config:      nil,
					Context:     nil,
					Supervised:  false,
				},
				AppProviderInsecure:        false,
				AppProviderPrefix:          "",
				ArchiverInsecure:           false,
				ArchiverPrefix:             "archiver",
				DatagatewayPrefix:          "data",
				Favorites:                  false,
				ProjectSpaces:              true,
				OCDavInsecure:              false, // true?
				OCDavPrefix:                "",
				OCSPrefix:                  "ocs",
				OCSSharePrefix:             defaultShareFolder,
				OCSHomeNamespace:           defaultStorageNamespace,
				PublicURL:                  defaultPublicURL,
				OCSCacheWarmupDriver:       "",
				OCSAdditionalInfoAttribute: "{{.Mail}}",
				OCSResourceInfoCacheTTL:    0,
				Middleware:                 config.Middleware{},
			},
			DataGateway: config.DataGatewayPort{
				Port:      config.Port{},
				PublicURL: "",
			},
			Gateway: config.Gateway{
				Port: config.Port{
					Endpoint:    defaultGatewayAddr,
					DebugAddr:   "127.0.0.1:9143",
					GRPCNetwork: "tcp",
					GRPCAddr:    defaultGatewayAddr,
				},
				CommitShareToStorageGrant:  true,
				CommitShareToStorageRef:    true,
				DisableHomeCreationOnLogin: false,
				ShareFolder:                "Shares",
				LinkGrants:                 "",
				HomeMapping:                "",
				EtagCacheTTL:               0,
			},
			StorageRegistry: config.StorageRegistry{
				Driver:       "spaces",
				HomeProvider: "/home", // unused for spaces, static currently not supported
				JSON:         "",
			},
			AppRegistry: config.AppRegistry{
				Driver:        "static",
				MimetypesJSON: "",
			},
			Users: config.Users{
				Port: config.Port{
					Endpoint:    "localhost:9144",
					DebugAddr:   "127.0.0.1:9145",
					GRPCNetwork: "tcp",
					GRPCAddr:    "127.0.0.1:9144",
					Services:    []string{"userprovider"},
				},
				Driver:                    "ldap",
				UserGroupsCacheExpiration: 5,
			},
			Groups: config.Groups{
				Port: config.Port{
					Endpoint:    "localhost:9160",
					DebugAddr:   "127.0.0.1:9161",
					GRPCNetwork: "tcp",
					GRPCAddr:    "127.0.0.1:9160",
					Services:    []string{"groupprovider"},
				},
				Driver:                      "ldap",
				GroupMembersCacheExpiration: 5,
			},
			AuthProvider: config.Users{
				Port:                      config.Port{},
				Driver:                    "ldap",
				UserGroupsCacheExpiration: 0,
			},
			AuthBasic: config.Port{
				GRPCNetwork: "tcp",
				GRPCAddr:    "127.0.0.1:9146",
				DebugAddr:   "127.0.0.1:9147",
				Services:    []string{"authprovider"},
				Endpoint:    "localhost:9146",
			},
			AuthBearer: config.Port{
				GRPCNetwork: "tcp",
				GRPCAddr:    "127.0.0.1:9148",
				DebugAddr:   "127.0.0.1:9149",
				Services:    []string{"authprovider"},
				Endpoint:    "localhost:9148",
			},
			AuthMachine: config.Port{
				GRPCNetwork: "tcp",
				GRPCAddr:    "127.0.0.1:9166",
				DebugAddr:   "127.0.0.1:9167",
				Services:    []string{"authprovider"},
				Endpoint:    "localhost:9166",
			},
			AuthMachineConfig: config.AuthMachineConfig{
				MachineAuthAPIKey: "change-me-please",
			},
			Sharing: config.Sharing{
				Port: config.Port{
					Endpoint:    "localhost:9150",
					DebugAddr:   "127.0.0.1:9151",
					GRPCNetwork: "tcp",
					GRPCAddr:    "127.0.0.1:9150",
					Services:    []string{"usershareprovider", "publicshareprovider"},
				},
				UserDriver:                       "json",
				UserJSONFile:                     path.Join(defaults.BaseDataPath(), "storage", "shares.json"),
				UserSQLUsername:                  "",
				UserSQLPassword:                  "",
				UserSQLHost:                      "",
				UserSQLPort:                      1433,
				UserSQLName:                      "",
				PublicDriver:                     "json",
				PublicJSONFile:                   path.Join(defaults.BaseDataPath(), "storage", "publicshares.json"),
				PublicPasswordHashCost:           11,
				PublicEnableExpiredSharesCleanup: true,
				PublicJanitorRunInterval:         60,
				UserStorageMountID:               "",
				Events: config.Events{
					Address:   "127.0.0.1:9233",
					ClusterID: "test-cluster",
				},
			},
			StorageShares: config.StoragePort{
				Port: config.Port{
					Endpoint:    "localhost:9154",
					DebugAddr:   "127.0.0.1:9156",
					GRPCNetwork: "tcp",
					GRPCAddr:    "127.0.0.1:9154",
					HTTPNetwork: "tcp",
					HTTPAddr:    "127.0.0.1:9155",
				},
				ReadOnly:      false,
				AlternativeID: "1284d238-aa92-42ce-bdc4-0b0000009154",
				MountID:       "1284d238-aa92-42ce-bdc4-0b0000009157",
			},
			StorageUsers: config.StoragePort{
				Port: config.Port{
					Endpoint:    "localhost:9157",
					DebugAddr:   "127.0.0.1:9159",
					GRPCNetwork: "tcp",
					GRPCAddr:    "127.0.0.1:9157",
					HTTPNetwork: "tcp",
					HTTPAddr:    "127.0.0.1:9158",
				},
				MountID:       "1284d238-aa92-42ce-bdc4-0b0000009157",
				Driver:        "ocis",
				DataServerURL: "http://localhost:9158/data",
				HTTPPrefix:    "data",
				TempFolder:    path.Join(defaults.BaseDataPath(), "tmp", "users"),
			},
			StoragePublicLink: config.PublicStorage{
				StoragePort: config.StoragePort{
					Port: config.Port{
						Endpoint:    "localhost:9178",
						DebugAddr:   "127.0.0.1:9179",
						GRPCNetwork: "tcp",
						GRPCAddr:    "127.0.0.1:9178",
					},
					MountID: "7993447f-687f-490d-875c-ac95e89a62a4",
				},
				PublicShareProviderAddr: "",
				UserProviderAddr:        "",
			},
			StorageMetadata: config.StoragePort{
				Port: config.Port{
					GRPCNetwork: "tcp",
					GRPCAddr:    "127.0.0.1:9215",
					HTTPNetwork: "tcp",
					HTTPAddr:    "127.0.0.1:9216",
					DebugAddr:   "127.0.0.1:9217",
				},
				Driver:           "ocis",
				ExposeDataServer: false,
				DataServerURL:    "http://localhost:9216/data",
				TempFolder:       path.Join(defaults.BaseDataPath(), "tmp", "metadata"),
				DataProvider:     config.DataProvider{},
			},
			AppProvider: config.AppProvider{
				Port: config.Port{
					GRPCNetwork: "tcp",
					GRPCAddr:    "127.0.0.1:9164",
					DebugAddr:   "127.0.0.1:9165",
					Endpoint:    "localhost:9164",
					Services:    []string{"appprovider"},
				},
				ExternalAddr: "127.0.0.1:9164",
				WopiDriver:   config.WopiDriver{},
				AppsURL:      "/app/list",
				OpenURL:      "/app/open",
				NewURL:       "/app/new",
			},
			Permissions: config.Port{
				Endpoint: "localhost:9191",
			},
			Configs:                     nil,
			UploadMaxChunkSize:          1e+8,
			UploadHTTPMethodOverride:    "",
			ChecksumSupportedTypes:      []string{"sha1", "md5", "adler32"},
			ChecksumPreferredUploadType: "",
			DefaultUploadProtocol:       "tus",
		},
		Tracing: config.Tracing{
			Service: "storage",
			Type:    "jaeger",
		},
		Asset: config.Asset{},
	}
}

func EnsureDefaults(cfg *config.Config) {
	// TODO: IMPLEMENT ME!
}

func Sanitize(cfg *config.Config) {
	// TODO: IMPLEMENT ME!
}
