/*
* Artcodes recognises a different marker scheme that allows the
* creation of aesthetically pleasing, even beautiful, codes.
* Copyright (C) 2013-2016 The University of Nottingham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package uk.ac.horizon.artcodes.account;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.util.Log;
import com.google.gson.Gson;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import okhttp3.Request;
import okhttp3.Response;
import uk.ac.horizon.artcodes.Artcodes;
import uk.ac.horizon.artcodes.GoogleAnalytics;
import uk.ac.horizon.artcodes.R;
import uk.ac.horizon.artcodes.model.Experience;
import uk.ac.horizon.artcodes.server.LoadCallback;
import uk.ac.horizon.artcodes.server.URILoaderCallback;
public class LocalAccount implements Account
{
private final Context context;
private final Gson gson;
public LocalAccount(Context context, Gson gson)
{
this.context = context;
this.gson = gson;
}
@Override
public String toString()
{
return getDisplayName();
}
@Override
public void loadLibrary(LoadCallback<List<String>> callback)
{
try
{
File directory = getDirectory();
Log.i("local", "Listing " + directory.getAbsolutePath());
List<String> result = new ArrayList<>();
SharedPreferences.Editor editor = context.getSharedPreferences(Account.class.getName(), Context.MODE_PRIVATE).edit();
for (final File file : directory.listFiles())
{
String uri = file.toURI().toString();
result.add(uri);
editor.putString(uri, getId());
}
editor.apply();
callback.loaded(result);
}
catch (Exception e)
{
callback.error(e);
}
}
@Override
public void saveExperience(final Experience experience)
{
this.saveExperience(experience, null);
}
@Override
public void saveExperience(final Experience experience, final AccountProcessCallback saveCallback)
{
try
{
File file;
if (experience.getId() == null || !canEdit(experience.getId()))
{
if (experience.getId() != null && (experience.getId().startsWith("http://") || experience.getId().startsWith("https://")))
{
experience.setOriginalID(experience.getId());
}
file = new File(getDirectory(), UUID.randomUUID().toString());
experience.setId(file.toURI().toString());
}
else
{
file = new File(URI.create(experience.getId()));
}
final FileWriter writer = new FileWriter(file);
gson.toJson(experience, writer);
writer.flush();
writer.close();
context.getSharedPreferences(Account.class.getName(), Context.MODE_PRIVATE)
.edit()
.putString(experience.getId(), getId())
.apply();
Log.i("local", experience.getId() + " = " + getId());
if (saveCallback!=null)
{
saveCallback.accountProcessCallback(true, experience);
}
}
catch (Exception e)
{
if (saveCallback!=null)
{
saveCallback.accountProcessCallback(false, null);
}
GoogleAnalytics.trackException(e);
}
}
@Override
public boolean equals(Object o)
{
return o instanceof Account && ((Account) o).getId().equals(getId());
}
@Override
public String getId()
{
return "local";
}
@Override
public String getDisplayName()
{
return context.getString(R.string.device);
}
@Override
public void setDisplayName(final String displayName)
{
}
@Override
public boolean canEdit(String uri)
{
final File directory = getDirectory();
final String directoryURI = directory.toURI().toString();
return uri != null && uri.startsWith(directoryURI);
}
@Override
public boolean isSaving(String uri)
{
return false;
}
@Override
public boolean isLocal()
{
return true;
}
@Override
public boolean load(final String uri, final URILoaderCallback callback)
{
if (uri.startsWith("content:") || uri.startsWith("file:"))
{
try
{
callback.onLoaded(new InputStreamReader(context.getContentResolver().openInputStream(Uri.parse(uri))));
return true;
}
catch (Exception e)
{
callback.onError(e);
}
}
else if (uri.startsWith("http:") || uri.startsWith("https:"))
{
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
final Request request = new Request.Builder()
.get()
.url(uri)
.addHeader("User-Agent", Artcodes.userAgent)
.build();
final Response response = Artcodes.httpClient.newCall(request).execute();
callback.onLoaded(response.body().charStream());
response.body().close();
}
catch (Exception e)
{
callback.onError(e);
}
}
}).start();
return true;
}
return false;
}
public void deleteExperience(Experience experience)
{
this.deleteExperience(experience, null);
}
public void deleteExperience(Experience experience, Account.AccountProcessCallback accountProcessCallback)
{
boolean success = true;
try
{
File file = new File(URI.create(experience.getId()));
if (!file.delete())
{
Log.w("local", "Experience " + experience.getId() + " not deleted");
success = false;
}
}
catch (Exception e)
{
GoogleAnalytics.trackException(e);
success = false;
}
if (accountProcessCallback!=null)
{
accountProcessCallback.accountProcessCallback(success, null);
}
}
public boolean validates()
{
return true;
}
private File getDirectory()
{
return context.getDir("experiences", Context.MODE_PRIVATE);
}
}