public static abstract class ApiCreator<T> implements Parcelable.Creator<T> {
    @Override
    public final T createFromParcel(Parcel source) {
        ApiParcelInputWrp wrp = new ApiParcelInputWrp(source);
        return create(wrp);
    }

    public abstract T create(ApiDataInput d);
} public static abstract class ApiParcelable extends ApiObject implements IApiParcelable {
    public int describeContents() {
        return 0;
    }

    public final void writeToParcel(Parcel dest, int flags) {
        baseWriteToParcel(this, dest, flags);
    }


    public static int baseDescribeContents() {
        return 0;
    }

    public static void baseWriteToParcel(IApiParcelable parcelable, Parcel dest, int flags) {
        ApiParcelOutputWrp p = new ApiParcelOutputWrp(dest);
        parcelable.save(p, flags);
    }
} public interface ApiDataInput extends ApiDataInputOutputBase {
    int getDataAppVersionCode(); // version code verze aplikace, ktera puvodne dana data ulozila...

    boolean readBoolean();
    int readInt();
    long readLong();

    byte[] readBytes();
    String readString();
    Bitmap readBitmap();
    <T extends IApiObject> T readObject(ApiCreator<T> creator);
    <T extends IApiParcelable> T readParcelableWithName();
    <T extends IApiObject> ImmutableList<T> readImmutableList(ApiCreator<T> creator);
    <T extends IApiParcelable> ImmutableList<T> readImmutableListWithNames();

    <T extends IApiParcelable> T readOptParcelableWithName();
} public interface ApiDataOutput extends ApiDataInputOutputBase {
    boolean write(boolean value);
    void write(int value);
    void write(long value);

    void write(byte[] value);
    void write(String value);
    void write(Bitmap value, int flags);
    void write(IApiObject value, int flags);
    void writeWithName(IApiParcelable value, int flags);
    void write(Collection<? extends IApiObject> value, int flags);
    void writeOpt(IApiObject value, int flags);
    void writeOptWithName(IApiParcelable value, int flags);
} public static class Couple<TFirst, TSecond> {
    private final TFirst first;
    private final TSecond second;

    public Couple(TFirst first, TSecond second) {
        this.first = first;
        this.second = second;
    }

    public TFirst getFirst() {
        return this.first;
    }

    public TSecond getSecond() {
        return this.second;
    }
} public static class NotImplementedException extends RuntimeException {
    public NotImplementedException() {}

} public class PromptDialog extends BaseDialogFragment {
    public static final String DEFAULT_FRAGMENT_TAG = PromptDialog.class.getName();

    private static final String BUNDLE_ID = "PromptDialog.id";
    private static final String BUNDLE_TITLE = "PromptDialog.title";
    private static final String BUNDLE_MESSAGE = "PromptDialog.message";
    private static final String BUNDLE_CALLBACK = "PromptDialog.callback";
    private static final String BUNDLE_CANCELABLE = "PromptDialog.cancelable";
    private static final String BUNDLE_SHOW_CANCEL_BTN = "PromptDialog.show_cancel_btn";
    private static final String BUNDLE_BTN_OK_TEXT = "PromptDialog.btn_ok_text";
    private static final String BUNDLE_BTN_CANCEL_TEXT = "PromptDialog.btn_cancel_text";
    private static final String BUNDLE_BUNDLE = "PromptDialog.bundle";

    private Bundle bundle;

    public static PromptDialog show(FragmentManager fm, DialogFragment oldDialog, String fragmentTagOpt, String id, CharSequence title, CharSequence message, boolean callback) {
        return show(fm, oldDialog, fragmentTagOpt, id, title, message, callback, false, false, null);
    }

    public static PromptDialog show(FragmentManager fm, DialogFragment oldDialog, String fragmentTagOpt, String id, CharSequence title, CharSequence message, boolean callback, boolean cancelable, boolean showCancelBtn, Bundle bundle) {
        return show(fm, oldDialog, fragmentTagOpt, id, title, message, callback, cancelable, showCancelBtn, bundle, null, null);
    }

    // btnOkText, btnCancelText - pokud jsou prazdne stringy (ne null!), vubec se nezobrazi
    public static PromptDialog show(FragmentManager fm, DialogFragment oldDialog, String fragmentTagOpt, String id, CharSequence title, CharSequence message, boolean callback, boolean cancelable, boolean showCancelBtn, Bundle bundle, CharSequence btnOkText, CharSequence btnCancelTxt) {
        PromptDialog ret = newInstance(id, title, message, callback, cancelable, showCancelBtn, bundle, btnOkText, btnCancelTxt);
        return FragmentUtils.showDialogRemoveOldOne(fm, oldDialog, ret, fragmentTagOpt == null ? DEFAULT_FRAGMENT_TAG : fragmentTagOpt);
    }

    public static PromptDialog newInstance(String id, CharSequence title, CharSequence message, boolean callback, boolean cancelable, boolean showCancelBtn, Bundle bundle, CharSequence btnOkText, CharSequence btnCancelTxt) {
        Bundle b = new Bundle();
        b.putString(BUNDLE_ID, id);
        b.putCharSequence(BUNDLE_TITLE, title);
        b.putCharSequence(BUNDLE_MESSAGE, message);
        b.putBoolean(BUNDLE_CALLBACK, callback);
        b.putBoolean(BUNDLE_CANCELABLE, cancelable);
        b.putBoolean(BUNDLE_SHOW_CANCEL_BTN, showCancelBtn);
        b.putCharSequence(BUNDLE_BTN_OK_TEXT, btnOkText);
        b.putCharSequence(BUNDLE_BTN_CANCEL_TEXT, btnCancelTxt);
        b.putBundle(BUNDLE_BUNDLE, bundle);

        PromptDialog ret = new PromptDialog();
        ret.setArguments(b);
        ret.setCancelable(cancelable);
        return ret;
    }


    @Override
    protected Builder build(Builder b, Bundle savedInstanceState) {
        Bundle a = getArguments();

        this.bundle = a.getBundle(BUNDLE_BUNDLE);

        final CharSequence title = a.getCharSequence(BUNDLE_TITLE);
        final CharSequence btnOkText = a.getCharSequence(BUNDLE_BTN_OK_TEXT);
        final CharSequence btnCancelText = a.getCharSequence(BUNDLE_BTN_CANCEL_TEXT);

        if (!TextUtils.isEmpty(title)) {
            b.setTitle(title);
        }
        b.setMessage(a.getCharSequence(BUNDLE_MESSAGE));
        if (!"".equals(btnOkText)) {
            b.setPositiveButton(btnOkText != null ? btnOkText : getString(android.R.string.ok), new OnClickListener() {
                @Override
                public void onClick(View v) {
                    onPromptDialogDone(getArguments().getString(BUNDLE_ID), false, bundle);
                    dismiss();
                }
            });
        }

        if (a.getBoolean(BUNDLE_CANCELABLE) && !"".equals(btnCancelText)) {
            b.setNegativeButton(btnCancelText != null ? btnCancelText : getString(android.R.string.cancel), new OnClickListener() {
                @Override
                public void onClick(View v) {
                    onPromptDialogDone(getArguments().getString(BUNDLE_ID), true, bundle);
                    dismiss();
                }
            });
        }
        return b;
    }

    @Override
    public void onStart() {
        super.onStart();
        if (getDialog() != null) {
            View v = getDialog().findViewById(R.id.sdl__message);
            if (v instanceof TextView) {
                ((TextView)v).setMovementMethod(LinkMovementMethod.getInstance()); // rozchozeni klikacich linku v message
            }
        }
    }

    @Override
    public void onCancel(DialogInterface dialog) {
        super.onCancel(dialog);
        onPromptDialogDone(getArguments().getString(BUNDLE_ID), true, bundle);
    }

    protected void onPromptDialogDone(String id, boolean canceled, Bundle bundle) {
        if (getArguments().getBoolean(BUNDLE_CALLBACK)) {
            if (this.getTargetFragment() != null) {
                ((OnPromptDialogDone)this.getTargetFragment()).onPromptDialogDone(id, canceled, bundle);
            }
            else if (this.getParentFragment() != null) {
                ((OnPromptDialogDone)this.getParentFragment()).onPromptDialogDone(id, canceled, bundle);
            }
            else {
                ((OnPromptDialogDone)this.getActivity()).onPromptDialogDone(id, canceled, bundle);
            }
        }
    }

    public interface OnPromptDialogDone {
        void onPromptDialogDone(String id, boolean canceled, Bundle bundle);
    }
} public interface OnPromptDialogDone {
    void onPromptDialogDone(String id, boolean canceled, Bundle bundle);
} public static class BaseError extends TaskError {
    public static final int OK = 0;
    public static final int UNKNOWN_ERROR = -1;
    public static final int SERVER_ERROR = -2;
    public static final int CONNECTION_ERROR_COMMUNICATION = -3;
    public static final int CONNECTION_ERROR_UNEXPECTED_RES = -4;
    public static final int FILE_ERROR = -5;
    public static final int LOGIN_ERROR = -6;

    public static final BaseError ERR_OK = new BaseError(OK, 0) {
        @Override
        public boolean isOk() {
            return true;
        }
    };
    public static final BaseError ERR_UNKNOWN_ERROR = new BaseError(UNKNOWN_ERROR, R.string.err_unknown_error);
    public static final BaseError ERR_SERVER_ERROR = new BaseError(SERVER_ERROR, R.string.err_server_error);
    public static final BaseError ERR_CONNECTION_ERROR_COMMUNICATION = new BaseError(CONNECTION_ERROR_COMMUNICATION, R.string.err_connection_error_communication);
    public static final BaseError ERR_CONNECTION_ERROR_UNEXPECTED_RES = new BaseError(CONNECTION_ERROR_UNEXPECTED_RES, R.string.err_connection_error_unexpected_res);
    public static final BaseError ERR_FILE_ERROR = new BaseError(FILE_ERROR, R.string.err_file_error);
    public static final BaseError ERR_LOGIN_ERROR = new BaseError(LOGIN_ERROR, R.string.err_login_error);
    // nezapomenout pridavat case vetve v ApiCreatoru!

    private final int id;
    private final int resId;

    private BaseError(int id, int resId) {
        this.id = id;
        this.resId = resId;
    }

    @Override
    public void save(ApiDataOutput d, int flags) {
        d.write(this.id);
    }

    public int getId() {
        return this.id;
    }

    public int getResId() {
        return this.resId;
    }

    @Override
    public int hashCode() {
        int _hash = 17;
        _hash = _hash * 29 + id;
        //_hash = _hash * 29 + resId;
        return _hash;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

        if (!(o instanceof BaseError)) {
            return false;
        }

        BaseError lhs = (BaseError) o;
        return lhs != null &&
                id == lhs.id;
        //resId == lhs.resId;
    }


    @Override
    public CharSequence getMsg(ITaskContext context) {
        return resId != 0 ? context.getAndroidContext().getString(resId) : "";
    }

    @Override
    public String getGoogleAnalyticsId() {
        return "BaseError:" + id;
    }

    public static boolean isConnectionError(ITaskError error) {
        return error instanceof BaseError
                && (((BaseError)error).id == CONNECTION_ERROR_COMMUNICATION || ((BaseError)error).id == CONNECTION_ERROR_UNEXPECTED_RES);
    }

    public static final ApiCreator<BaseError> CREATOR = new ApiCreator<BaseError>() {
        public BaseError create(ApiDataInput d) {
            int id = d.readInt();
            switch (id) {
                case OK: return ERR_OK;
                case UNKNOWN_ERROR: return ERR_UNKNOWN_ERROR;
                case SERVER_ERROR: return ERR_SERVER_ERROR;
                case CONNECTION_ERROR_COMMUNICATION: return ERR_CONNECTION_ERROR_COMMUNICATION;
                case CONNECTION_ERROR_UNEXPECTED_RES: return ERR_CONNECTION_ERROR_UNEXPECTED_RES;
                case FILE_ERROR: return ERR_FILE_ERROR;
                case LOGIN_ERROR: return ERR_LOGIN_ERROR;
                default: throw new NotImplementedException();
            }
        }

        public BaseError[] newArray(int size) { return new BaseError[size]; }
    };
} public interface ITaskError extends IApiParcelable {
    boolean isOk();
    CharSequence getMsg(ITaskContext context);
    //DialogFragment createDialog(ITaskContext context, boolean finish);
    void showToast(ITaskContext context);
    TaskException createExc(ITaskContext context);
    String getGoogleAnalyticsId();
} public class ActivityUtils {
    private static final String ACTIVITY_RESULT_PARCELABLE = ActivityUtils.class.getName() + "." + "ACTIVITY_RESULT_PARCELABLE";

    public static void setResultParcelable(Activity activity, int resultCode, Parcelable data) {
        Intent intent = new Intent();
        intent.putExtra(ACTIVITY_RESULT_PARCELABLE, data);
        activity.setResult(resultCode, intent);
    }

    public static <T extends Parcelable> T getResultParcelable(Intent resultData) {
        return resultData != null ? resultData.<T>getParcelableExtra(ACTIVITY_RESULT_PARCELABLE) : null;
    }

} public class EqualsUtils {
    public static int HASHCODE_INVALID = 654123456;
    public static int HASHCODE_INVALID_REPLACEMENT = 654123457;

    public static <T> int hashCodeCheckNull(T o) {
        return o == null ? 0 : o.hashCode();
    }

    public static <T> boolean equalsCheckNull(T lhs, T rhs) {
        return lhs == null ? rhs == null : lhs.equals(rhs);
    }

    public static int itemsHashCode(List<?> items) {
        int result = 17;
        if (items != null) {
            for (int i = 0; i < items.size(); i++) {
                result = 31 * result + (items.get(i) == null ? 0 : items.get(i).hashCode());
            }
        }
        return result;
    }

    public static int itemsHashCode(int[] items) {
        int result = 17;
        if (items != null) {
            for (int i = 0; i < items.length; i++) {
                result = 31 * result + items[i];
            }
        }
        return result;
    }


    public static boolean itemsEqual(List<?> lhs, List<?> rhs) {
        if (lhs == rhs)
            return true;
        if (lhs == null || rhs == null)
            return false;
        if (lhs.size() != rhs.size())
            return false;

        for (int i = 0; i < lhs.size(); i++) {
            if (lhs.get(i) == null) {
                if (rhs.get(i) != null)
                    return false;
            }
            else if (!lhs.get(i).equals(rhs.get(i))) {
                return false;
            }
        }
        return true;
    }

    public static boolean itemsEqual(int[] lhs, int[] rhs) {
        if (lhs == rhs)
            return true;
        if (lhs == null || rhs == null || lhs.length != rhs.length)
            return false;

        for (int i = 0; i < lhs.length; i++) {
            if (lhs[i] != rhs[i])
                return false;
        }
        return true;
    }

    public static int itemsOfItemsHashCode(List<? extends List<?>> items) {
        int result = 17;
        if (items != null) {
            for (int i = 0; i < items.size(); i++) {
                result = 31 * result + itemsHashCode(items.get(i));
            }
        }
        return result;
    }

    public static boolean itemsOfItemsEqual(List<? extends List<?>> lhs, List<? extends List<?>> rhs) {
        if (lhs == rhs)
            return true;
        if (lhs == null || rhs == null)
            return false;
        if (lhs.size() != rhs.size())
            return false;

        for (int i = 0; i < lhs.size(); i++) {
            if (!itemsEqual(lhs.get(i), rhs.get(i))) {
                return false;
            }
        }
        return true;
    }
} public class LogUtils {
    private static final int MIN_LOG_TO_FILE_COUNT = 400;
    private static final int MAX_LOG_TO_FILE_COUNT = 500;
    private static final DateFormat DATE_FORMATTER = new SimpleDateFormat("[yyyy.MM.dd HH:mm:ss:SSS]", Locale.getDefault());
//    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormat.forPattern("[yyyy.MM.dd HH:mm:ss:SSS]");

    private static boolean logcatEnabled;

    private static File logFile = null;
    private static PrintStream logFileStream = null;
    private static final ArrayList<String> logEntries = new ArrayList<>(MAX_LOG_TO_FILE_COUNT); // uchovava posledni logy v pameti - at uz zapisujeme nebo nezapisujeme do log filu

    public static void setLoggingEnabled(boolean logcatEnabled) {
        LogUtils.logcatEnabled = logcatEnabled;
    }

    private static void closeLogFile() {
        if (logFileStream != null) {
            logFileStream.close();
            logFileStream = null;
        }
    }

    private static void openLogFile(boolean append) {
        try {
            logFileStream = new PrintStream(new BufferedOutputStream(new FileOutputStream(logFile, append)));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    private static void logToArrayList(String type, String tag, String text, Throwable optTr) {
        StringBuilder s = new StringBuilder(DATE_FORMATTER.format(new Date()));
        s.append(" ");
        s.append(type).append(":").append(tag).append(": ").append(text);

        if (optTr != null) {
            s.append("\n");
            s.append(Log.getStackTraceString(optTr));
        }
        String newLine = s.toString();

        synchronized (logEntries) {
            if (logEntries.size() >= MAX_LOG_TO_FILE_COUNT) {
                logEntries.subList(0,  logEntries.size() - MIN_LOG_TO_FILE_COUNT).clear();

                // pokud mame k dispozici soubor pro logovani, tak jdeme zapisovat
                if (logFile != null) {
                    closeLogFile();
                    openLogFile(false);

                    for (String line : logEntries) {
                        logFileStream.println(line);
                    }
                }
            }
            logEntries.add(newLine);

            if (logFile != null) {
                logFileStream.println(newLine);
                logFileStream.flush();
            }
        }
    }


    /**
     * Wraps {@link android.util.Log#i}.
     *
     * @param tag
     * @param string
     */
    public static void i(String tag, String string) {
        //if (logcatEnabled) {
        Log.i(tag, string);
        //}
        logToArrayList("i", tag, string, null);
    }

    /**
     * Wraps {@link android.util.Log#e}.
     *
     * @param tag
     * @param string
     */
    public static void e(String tag, String string) {
        //if (logcatEnabled) {
        Log.e(tag, string);
        //}
        logToArrayList("e", tag, string, null);
    }

    /**
     * Wraps {@link android.util.Log#e}.
     *
     * @param tag
     * @param string
     */
    public static void e(String tag, String string, Throwable tr) {
        //if (logcatEnabled) {
        Log.e(tag, string, tr);
        //}
        logToArrayList("e", tag, string, tr);
    }

    /**
     * Wraps {@link android.util.Log#d}.
     *
     * @param tag
     * @param string
     */
    public static void d(String tag, String string) {
        if (logcatEnabled) {
            Log.d(tag, string);
        }
        logToArrayList("d", tag, string, null);
    }

    /**
     * Wraps {@link android.util.Log#w}.
     *
     * @param tag
     * @param string
     */
    public static void w(String tag, String string) {
        if (logcatEnabled) {
            Log.w(tag, string);
        }
        logToArrayList("w", tag, string, null);
    }


    /**
     * Wraps {@link android.util.Log#d}.
     *
     * @param tag
     * @param value
     */
    public static void d(String tag, int value) {
        d(tag, String.valueOf(value));
    }
} public class ViewUtils {
    private static float baseScale = 1;

    public static void setBaseScale(float baseScale) {
        ViewUtils.baseScale = baseScale;
    }

    public static int getScaledDensityDpi(Context context) {
        return (int)((context.getResources().getDisplayMetrics().densityDpi * baseScale) + 0.5f);
    }

    public static int getPixelsFromDp(Context context, float dp) {
        return getPixelsFromDp(context, dp, baseScale);
    }

    public static int getPixelsFromDp(Context context, float dp, float baseScale) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) ((dp * scale * baseScale) + 0.5f);
    }

    public static float getPixelsFromSp(Context context, float sp) {
        final float scale = context.getResources().getDisplayMetrics().scaledDensity;
        return sp * scale * baseScale;
    }

    public static void setTextOrHide(TextView textView, CharSequence text) {
        if (!TextUtils.isEmpty(text)) {
            textView.setVisibility(TextView.VISIBLE);
            textView.setText(text);
        }
        else
            textView.setVisibility(TextView.GONE);
    }

    @SuppressWarnings("deprecation")
    public static void setBackgroundDrawableKeepPadding(View view, Drawable drawable) {
        int left = view.getPaddingLeft();
        int top = view.getPaddingTop();
        int right = view.getPaddingRight();
        int bottom = view.getPaddingBottom();

        view.setBackgroundDrawable(drawable);
        view.setPadding(left, top, right, bottom);
    }

    public static void setBackgroundResourceKeepPadding(View view, int resid) {
        int left = view.getPaddingLeft();
        int top = view.getPaddingTop();
        int right = view.getPaddingRight();
        int bottom = view.getPaddingBottom();

        view.setBackgroundResource(resid);
        view.setPadding(left, top, right, bottom);
    }

    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
        int result = size;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize =  MeasureSpec.getSize(measureSpec);
        switch (specMode) {
            case MeasureSpec.UNSPECIFIED:
                result = size;
                break;
            case MeasureSpec.AT_MOST:
                if (specSize < size) {
                    result = specSize | View.MEASURED_STATE_TOO_SMALL;
                } else {
                    result = size;
                }
                break;
            case MeasureSpec.EXACTLY:
                result = specSize;
                break;
        }
        return result | (childMeasuredState & View.MEASURED_STATE_MASK);
    }

    public static void addOnGlobalLayoutCalledOnce(final View view, final OnGlobalLayoutListener l) {
        view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                ViewTreeObserver vto = view.getViewTreeObserver();
                if (vto != null && vto.isAlive()) {
                    if (VERSION.SDK_INT < VERSION_CODES.JELLY_BEAN)
                        vto.removeGlobalOnLayoutListener(this);
                    else
                        vto.removeOnGlobalLayoutListener(this);
                }
                l.onGlobalLayout();
            }
        });
    }

    public static void addOnTextChangedAndLayout(final TextView view, final OnTextChangedAndLayoutListener listener) {
        view.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
                if (view.getLineCount() <= 0) {
                    ViewUtils.addOnGlobalLayoutCalledOnce(view, new OnGlobalLayoutListener() {
                        @Override
                        public void onGlobalLayout() {
                            listener.onTextChangedAndLayout(view);
                        }
                    });
                } else
                    listener.onTextChangedAndLayout(view);
            }
        });
    }



    public interface OnTextChangedAndLayoutListener {
        void onTextChangedAndLayout(TextView view);
    }
} public static class ChangeHomescreenActivityResult extends ApiParcelable {
    public final byte[] homescreen;

    public ChangeHomescreenActivityResult(byte[] homescreen) {
        this.homescreen = homescreen;
    }

    public ChangeHomescreenActivityResult(ApiDataInput d) {
        this.homescreen = d.readBytes();
    }

    @Override
    public void save(ApiDataOutput d, int flags) {
        d.write(this.homescreen);
    }

    public static final ApiCreator<ChangeHomescreenActivityResult> CREATOR = new ApiCreator<ChangeHomescreenActivityResult>() {
        public ChangeHomescreenActivityResult create(ApiDataInput d) { return new ChangeHomescreenActivityResult(d); }
        public ChangeHomescreenActivityResult[] newArray(int size) { return new ChangeHomescreenActivityResult[size]; }
    };
} public abstract class BaseActivity extends AppCompatActivity implements IBaseFragmentActivity, ITaskFragmentActivity, IDialogsFragmentActivity, OnRequestPermissionsResultCallback, ITaskResultListener {
    private static final String DIALOG_CONFIRM_ACTION = "BaseActivity.DIALOG_CONFIRM_ACTION";

    private GlobalContext gct;
    private TaskFragment taskFragment;
	private DialogsFragment dialogsFragment;
    private final ArrayList<OnBackPressedListener> onBackPressedListeners = new ArrayList<>();
    private final List<Runnable> pendingTasks = new ArrayList<Runnable>();
    private boolean readyToCommitFragments = false;
    private INavDrawerCallbacks navDrawerCallbacks;

    // pokud je false a pokud nedochazi pouze ke zmene konfigurace (nejcasteji kvuli otoceni displeje), pri kazdem volani onStop dojde k odpojeni trezoru
    // aktivita muze nastavit na true, aby pri prechodu z jedne aktivity do druhe nedochazelo ke zbytecnemu odpojovani
    // V kazdem pripade pri kazdem volani onStop (a onCreate) je nastaveno zpet na false
    private boolean dontDisconnectOnStop = false;

    // Saved state
    private PromptDialog dialogConfirmAction;


    //
    // LIFECYCLE CALLBACKS
    //

	@Override
	protected void onCreate(Bundle savedInstanceState) {
	    this.gct = GlobalContext.get();
        super.onCreate(savedInstanceState);
        onBackPressedListeners.clear(); // pro jistotu...
        readyToCommitFragments = false;
        trezorConnectionChangedReceiver.register(this);
        dontDisconnectOnStop = false;

        this.dialogConfirmAction = (PromptDialog)getSupportFragmentManager().findFragmentByTag(DIALOG_CONFIRM_ACTION);
	}

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == GlobalContext.RQC_ENTER_PIN) {
            EnterPinActivityResult res = ActivityUtils.getResultParcelable(data);
            executeTrezorTaskIfCan(
                    res.param.taskId,
                    new TrezorTaskParam(resultCode == RESULT_OK ? PinMatrixAck.newBuilder().setPin(res.pinEncoded).build() : Cancel.newBuilder().build(), res.param.tag));
        }
        else if (requestCode == GlobalContext.RQC_ENTER_PASSPHRASE) {
            EnterPassphraseActivityResult res = ActivityUtils.getResultParcelable(data);
            executeTrezorTaskIfCan(
                    res.param.taskId,
                    new TrezorTaskParam(resultCode == RESULT_OK ? PassphraseAck.newBuilder().setPassphrase(res.passphrase).build() : Cancel.newBuilder().build(), res.param.tag));
        }
        else
            super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    protected void onStart() {
        super.onStart();

        if (this.navDrawerCallbacks != null)
            this.navDrawerCallbacks.onActivityStart();
    }

    @Override
    protected void onResume() {
        super.onResume();
        this.readyToCommitFragments = true;

        ArrayList<Runnable> pendingTasksCopy = new ArrayList<Runnable>(this.pendingTasks);
        this.pendingTasks.clear(); // pro jistotu vymazu uz tady a misto toho prochazim pendingTasksCopy

        for (Runnable r : pendingTasksCopy)
            r.run();
    }

    @Override
    protected void onPause() {
        this.readyToCommitFragments = false;
        super.onPause();
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (this.navDrawerCallbacks != null)
            this.navDrawerCallbacks.onActivityStop();

        if (!dontDisconnectOnStop && !isChangingConfigurations()) {
            gct.executeDisconnectTrezorTask();
        }
        dontDisconnectOnStop = false;
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        this.readyToCommitFragments = false;
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        onBackPressedListeners.clear(); // pro jistotu...
        trezorConnectionChangedReceiver.unregister(this);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            finish();
            return true;
        }
        else
            return super.onOptionsItemSelected(item);
    }

    @Override
    public void onRequestPermissionsResult(final int requestCode, final @NonNull String[] permissions, final @NonNull int[] grantResults) {
        if (isReadyToCommitFragments()) {
            OnRequestPermissionsResultReceiver.sendBroadcast(this, requestCode, permissions, grantResults);
        }
        else {
            addPendingTask(new Runnable() {
                @Override
                public void run() {
                    OnRequestPermissionsResultReceiver.sendBroadcast(BaseActivity.this, requestCode, permissions, grantResults);
                }
            });
        }
    }


    //
    // GETTERS
    //

	@Override
	public TaskFragment getTaskFragment() {
		if (taskFragment == null) {
			this.taskFragment = TaskFragment.getInstance(this);
		}
		return taskFragment;
	}

    @Override
	public DialogsFragment getDialogsFragment() {
		if (dialogsFragment == null) {
			this.dialogsFragment = DialogsFragment.getInstance(this);
		}
		return dialogsFragment;
	}

    @Override
    public void onBackPressed() {
        // projdeme seznam od konce...
        for (int i = onBackPressedListeners.size() - 1; i >= 0; --i) {
            if (onBackPressedListeners.get(i).onBackPressed()) {
                return; // koncime...
            }
        }
        if (!onBackPressedAfterListeners())
            super.onBackPressed();
    }

    public boolean onBackPressedAfterListeners() {
        return false;
    }

    @Override
    public void addOnBackPressedListener(OnBackPressedListener l) {
        onBackPressedListeners.remove(l); // pro jistotu... navic chceme, aby listener byl v seznamu posledni
        onBackPressedListeners.add(l);
    }

    @Override
    public void removeOnBackPressedListener(OnBackPressedListener l) {
        onBackPressedListeners.remove(l);
    }


    public void addPendingTask(Runnable task) {
        this.pendingTasks.add(task);
    }

    public boolean isReadyToCommitFragments() {
        return readyToCommitFragments;
    }

    public void setNavDrawerCallbacks(INavDrawerCallbacks navDrawerCallbacks) {
        this.navDrawerCallbacks = navDrawerCallbacks;
    }


    public void setDontDisconnectOnStop() {
        this.dontDisconnectOnStop = true;
    }

    public void executeTrezorTaskIfCan(String taskId, Message msgParam) {
        executeTrezorTaskIfCan(taskId, new TrezorTaskParam(msgParam));
    }

    public void executeTrezorTaskIfCan(String taskId, TrezorTaskParam param) {
        if (!getTaskFragment().containsAnyTaskByFragmentTag(null)) {
            getTaskFragment().executeTask(taskId, param, null, false, null);
        }
    }

    protected boolean canHandleButtonReqByDefAction() {
        return false;
    }

    @Override
    public final void onTaskCompleted(String id, ITaskResult result, Bundle bundle) {
        if (result instanceof TrezorTaskResult) {
            TrezorTaskResult res = (TrezorTaskResult)result;
            beforeTrezorTaskCompleted(id, res);

            if (dialogConfirmAction != null) {
                dialogConfirmAction.dismiss();
                dialogConfirmAction = null;
            }

            if (res.isValidResult()) {
                switch (res.getMsgResult().msgType) {
                    case MessageType_PinMatrixRequest:
                        startActivityForResult(EnterPinActivity.createIntent(this, new EnterPinActivityParam(id, res.getParam().getTag(), ((PinMatrixRequest) res.getMsgResult().msg).getType())),
                                GlobalContext.RQC_ENTER_PIN);
                        setDontDisconnectOnStop();
                        break;

                    case MessageType_EntropyRequest: {
                        SecureRandom random = new SecureRandom();
                        byte[] entropy = new byte[32];
                        random.nextBytes(entropy);
                        EntropyAck param = EntropyAck.newBuilder().setEntropy(ByteString.copyFrom(entropy)).build();
                        executeTrezorTaskIfCan(id, new TrezorTaskParam(param, res.getParam().getTag()));
                        break;
                    }

                    case MessageType_PassphraseRequest: {
                        startActivityForResult(EnterPassphraseActivity.createIntent(this, new EnterPassphraseActivityParam(id, res.getParam().getTag())),
                                GlobalContext.RQC_ENTER_PASSPHRASE);
                        setDontDisconnectOnStop();
                        break;
                    }

                    case MessageType_ButtonRequest: {
                        if (canHandleButtonReqByDefAction()) {
                            this.dialogConfirmAction = PromptDialog.show(getSupportFragmentManager(), dialogConfirmAction, DIALOG_CONFIRM_ACTION, DIALOG_CONFIRM_ACTION, "", getString(R.string.confirm_action_on_trezor),
                                    false, false, false, null, "", "");
                            executeTrezorTaskIfCan(id, ButtonAck.newBuilder().build());
                        }
                        else
                            onTrezorTaskCompletedSucc(id, res);
                        break;
                    }

                    default:
                        onTrezorTaskCompletedSucc(id, res);
                }
            }
            else {
                onTrezorError(res.getError());
            }
        }
        else
            onOtherTaskCompleted(id, result, bundle);
    }

    public void onOtherTaskCompleted(String id, ITaskResult result, Bundle bundle) {
    }

    public void beforeTrezorTaskCompleted(String id, TrezorTaskResult res) {
    }

    public void onTrezorTaskCompletedSucc(String id, TrezorTaskResult res) {
    }

    public void onTrezorConnected() {
    }

    public void onTrezorError(ITaskError error) {
        error.showToast(gct);

        gct.getCommonDb().removeAllTrezors();
        gct.executeDisconnectTrezorTask();
        finish();
        startActivity(MainActivity.createIntent(BaseActivity.this));
        setDontDisconnectOnStop();

        if (BaseActivity.this instanceof MainActivity) {
            overridePendingTransition(0, 0);
        }
    }

    public void showToastTrezorMsgFailure(Failure failure) {
        final String s;

        if (failure != null) {
            if (failure.hasMessage())
                s = failure.getMessage();
            else if (failure.hasCode())
                s = failure.getCode().name();
            else
                s = getString(R.string.trezor_err_unexpected_response);
        }
        else
            s = getString(R.string.trezor_err_unexpected_response);

        Toast.makeText(this, s, Toast.LENGTH_LONG).show();
    }

    private final TrezorConnectionChangedReceiver trezorConnectionChangedReceiver = new TrezorConnectionChangedReceiver() {
        @Override
        public void onTrezorConnectionChanged(boolean connected) {
            pendingTasks.remove(pendingTaskTrezorConnected);
            pendingTasks.remove(pendingTaskTrezorDisconnected);

            Runnable task = connected ? pendingTaskTrezorConnected : pendingTaskTrezorDisconnected;

            if (isReadyToCommitFragments())
                task.run();
            else
                addPendingTask(task);
        }
    };

    private final Runnable pendingTaskTrezorConnected = new Runnable() {
        @Override
        public void run() {
            onTrezorConnected();
        }
    };

    private final Runnable pendingTaskTrezorDisconnected = new Runnable() {
        @Override
        public void run() {
            onTrezorError(TrezorError.ERR_NOT_CONNECTED);
        }
    };


    //
    // INNER CLASSES
    //


    /**
     * POZOR Je potreba zajistit, aby byl receiver zaregistrovan dostatecne brzo - bud v onStart, nebo alespon v onResume pred volanim super.onResume!
     */
    public static abstract class OnRequestPermissionsResultReceiver extends BaseLocalReceiver {
        public static final int RQC_COMMON = 0;
        public static final int RQC_ACCESS_FINE_LOC = 100;

        private static final String ACTION = OnRequestPermissionsResultReceiver.class.getName() + ".ACTION";

        public OnRequestPermissionsResultReceiver() {
            super(ACTION);
        }

        public static void sendBroadcast(Context context, int requestCode, String[] permissions, int[] grantResults) {
            Intent intent = new Intent(ACTION)
                    .putExtra("requestCode", requestCode)
                    .putExtra("permissions", permissions)
                    .putExtra("grantResults", grantResults);
            sendBroadcast(context, intent);
        }

        @Override
        public void onReceiveRegistered(Context context, Intent intent) {
            onRequestPermissionsResultReceived(
                    context,
                    intent.getIntExtra("requestCode", 0),
                    intent.getStringArrayExtra("permissions"),
                    intent.getIntArrayExtra("grantResults")
            );
        }

        public abstract void onRequestPermissionsResultReceived(Context context, int requestCode, String[] permissions, int[] grantResults);

        public static boolean isPermissionGranted(String permissionToFind, String[] permissions, int[] grantResults) {
            int ind = tryFindPermissionInd(permissionToFind, permissions);
            return ind >= 0 && grantResults[ind] == PackageManager.PERMISSION_GRANTED;
        }

        public static int tryFindPermissionInd(String permissionToFind, String[] permissions) {
            for (int i = 0; i < permissions.length; i++) {
                if (EqualsUtils.equalsCheckNull(permissionToFind, permissions[i])) {
                    return i;
                }
            }
            return -1;
        }
    }
} public class GlobalContext extends GlobalContextLib {
    private static final String TAG = GlobalContext.class.getSimpleName();

    public static final int RQC_ENTER_PIN = 701;
    public static final int RQC_PICK_HOMESCREEN = 702;
    public static final int RQC_PICK_CUSTOM_IMAGE = 703;
    public static final int RQC_ENTER_PASSPHRASE = 704;
    //public static final int RQC_INIT_TREZOR = 705;

    private static final String FIRMWARE_DIR_V1 = "firmware";
    private static final String FIRMWARE_DIR_V2 = "firmware-v2";
    private static final String FIRMWARE_FILE_PREFIX = "trezor-";
    private static final String FIRMWARE_FILE_POSTFIX = ".bin";

    private final TrezorManager trezorManager;

    private CommonDb commonDb;
    private FirmwareReleases firmwareReleases;

    static void init(Context context) {
        GlobalContextLib.init(new GlobalContext(context));
    }

    public static GlobalContext get() {
        return (GlobalContext)GlobalContextLib.get();
    }

    private GlobalContext(Context context) {
        super(context);
        LogUtils.setLoggingEnabled(!getAppIsInProductionMode());
        this.trezorManager = new TrezorManager(context);
    }

    public TrezorManager getTrezorManager() {
        return trezorManager;
    }


    @Override
    public void requestGoogleBackupIfNeeded(String changedDbFileName) {
    }

    @Override
    public String getCurrentLangAbbrev() {
        return Locale.getDefault().getLanguage();
    }

    public synchronized CommonDb getCommonDb() {
        if (this.commonDb == null) {
            LogUtils.d(TAG, "Before creating CommonDb");
            this.commonDb = new CommonDb(this);
            LogUtils.d(TAG, "After creating CommonDb");
        }
        return this.commonDb;
    }


    public synchronized FirmwareReleases getFirmwareReleases(boolean isV2) {
        if (this.firmwareReleases == null || this.firmwareReleases.isV2 != isV2) {
            this.firmwareReleases = null;
            LogUtils.d(TAG, "Before loading releases.json, isV2: " + isV2);
            BufferedReader releasesReader = null;
            final String firmwareDir = isV2 ? FIRMWARE_DIR_V2 : FIRMWARE_DIR_V1;

            try {
                releasesReader = new BufferedReader(new InputStreamReader(getAndroidContext().getAssets().open(firmwareDir + File.separatorChar + "releases.json", AssetManager.ACCESS_BUFFER), "UTF-8"));
                StringBuilder bRelease = new StringBuilder();

                String line;
                while ((line = releasesReader.readLine()) != null) {
                    bRelease.append(line).append('\n');
                }

                JSONArray jReleases = new JSONArray(bRelease.toString());
                ArrayList<FirmwareRelease> versions = new ArrayList<>();

                for (int i = 0; i < jReleases.length(); i++) {
                    JSONObject jRelease = jReleases.getJSONObject(i);
                    JSONArray jVersion = jRelease.getJSONArray("version");

                    versions.add(new FirmwareRelease(
                            jRelease.getBoolean("required"),
                            new FirmwareVersion(jVersion.getInt(0), jVersion.getInt(1), jVersion.getInt(2)),
                            jRelease.optString("fingerprint", ""),
                            jRelease.getString("changelog")));
                }

                Collections.sort(versions, Collections.reverseOrder());
                this.firmwareReleases = new FirmwareReleases(isV2, ImmutableList.copyOf(versions));
            }
            catch (Exception e) {
                LogUtils.e(TAG, "getBundledFirmwareVersion", e);
                this.firmwareReleases = FirmwareReleases.createInvalid(isV2);
            }
            finally {
                if (releasesReader != null) {
                    try {
                        releasesReader.close();
                    } catch (IOException e) {
                        LogUtils.e(TAG, "getBundledFirmwareVersion (closing releaseReader)", e);
                    }
                }
            }
            LogUtils.d(TAG, "After loading bundled firmware version");
        }
        return this.firmwareReleases;
    }

    public synchronized InputStream openStreamBundledFirmware(boolean isV2) throws IOException {
        FirmwareRelease f = getFirmwareReleases(isV2).getNewest();
        return getAndroidContext().getAssets().open((isV2 ? FIRMWARE_DIR_V2 : FIRMWARE_DIR_V1) + File.separatorChar + FIRMWARE_FILE_PREFIX + f.version.major + "." + f.version.minor + "." + f.version.patch + FIRMWARE_FILE_POSTFIX);
    }

    public synchronized void executeDisconnectTrezorTask() {
        // schvalne resime takto globalne pres taskExecutor, protoze kazdopadne nechceme, aby se task (cekajici ve fronte) zrusil napr. pri zavreni aktivity...
        getTaskExecutor().executeTask("TASK_DISCONNECT_TREZOR_GCT",
                new AsyncTaskParam(TrezorTaskParam.SERIAL_EXECUTION_KEY_TREZOR) {
                    @Override
                    public boolean isExecutionInParallelForbidden(ITaskContext context) {
                        return true;
                    }

                    @Override
                    public void execute(ITaskContext context, ITask task) throws TaskException {
                        getTrezorManager().closeDeviceConnection();
                    }
                },
                null,
                false,
                new EmptyTaskListener(),
                null);
    }


    public static class FirmwareReleases {
        public static final FirmwareReleases createInvalid(boolean isV2) {
            return new FirmwareReleases(isV2, ImmutableList.<FirmwareRelease>of());
        }

        public final boolean isV2;
        public final ImmutableList<FirmwareRelease> releasesDesc; // sorted from the newest to oldest

        // upraveno: versionsDesc
        public FirmwareReleases(boolean isV2, ImmutableList<FirmwareRelease> releasesDesc) {
            this.isV2 = isV2;
            this.releasesDesc = releasesDesc;
        }

        public FirmwareRelease getNewest() {
            return releasesDesc.size() > 0 ? releasesDesc.get(0) : null;
        }

        public boolean isUpdateRequired(FirmwareVersion deviceVersion) {
            if (!deviceVersion.isValid())
                return false;

            for (FirmwareRelease r : releasesDesc) {
                if (!r.version.isNewerThan(deviceVersion))
                    return false;

                if (r.required)
                    return true;
            }
            return false;
        }
    }

    public static class FirmwareRelease implements Comparable<FirmwareRelease> {
        public final boolean required;
        public final FirmwareVersion version;
        public final String fingerprint;
        public final String changelog;

        public FirmwareRelease(boolean required, FirmwareVersion version, String fingerprint, String changelog) {
            this.required = required;
            this.version = version;
            this.fingerprint = fingerprint;
            this.changelog = changelog;
        }

        @Override
        public int compareTo(@NonNull FirmwareRelease v) {
            return version.compareTo(v.version);
        }

        @Override
        public String toString() {
            return version.toString();
        }
    }

    public static class FirmwareVersion implements Comparable<FirmwareVersion> {
        public static final FirmwareVersion INVALID = new FirmwareVersion(0, 0, 0);

        public final int major;
        public final int minor;
        public final int patch;

        public static FirmwareVersion create(Features features) {
            if (features.getBootloaderMode()) {
                return (features.hasFwMajor() && features.hasFwMinor() && features.hasFwPatch() && features.getFwMajor() > 0) ?
                        new FirmwareVersion(features.getFwMajor(), features.getFwMinor(), features.getFwPatch()) : FirmwareVersion.INVALID;
            }
            else
                return new FirmwareVersion(features.getMajorVersion(), features.getMinorVersion(), features.getPatchVersion());
        }

        public FirmwareVersion(int major, int minor, int patch) {
            this.major = major;
            this.minor = minor;
            this.patch = patch;
        }

        public boolean isValid() {
            return major != 0 || minor != 0 || patch != 0;
        }

        public boolean isNewerThan(FirmwareVersion v) {
            return compareTo(v) > 0;
        }

        @Override
        public int compareTo(@NonNull FirmwareVersion v) {
            if (this.major != v.major)
                return this.major < v.major ? -1 : 1;
            else if (this.minor != v.minor)
                return this.minor < v.minor ? -1 : 1;
            else if (this.patch != v.patch)
                return this.patch < v.patch ? -1 : 1;
            else
                return 0;
        }

        @Override
        public String toString() {
            return major + "." + minor + "." + patch;
        }
    }
} public static class FirmwareRelease implements Comparable<FirmwareRelease> {
    public final boolean required;
    public final FirmwareVersion version;
    public final String fingerprint;
    public final String changelog;

    public FirmwareRelease(boolean required, FirmwareVersion version, String fingerprint, String changelog) {
        this.required = required;
        this.version = version;
        this.fingerprint = fingerprint;
        this.changelog = changelog;
    }

    @Override
    public int compareTo(@NonNull FirmwareRelease v) {
        return version.compareTo(v.version);
    }

    @Override
    public String toString() {
        return version.toString();
    }
} public static class FirmwareReleases {
    public static final FirmwareReleases createInvalid(boolean isV2) {
        return new FirmwareReleases(isV2, ImmutableList.<FirmwareRelease>of());
    }

    public final boolean isV2;
    public final ImmutableList<FirmwareRelease> releasesDesc; // sorted from the newest to oldest

    // upraveno: versionsDesc
    public FirmwareReleases(boolean isV2, ImmutableList<FirmwareRelease> releasesDesc) {
        this.isV2 = isV2;
        this.releasesDesc = releasesDesc;
    }

    public FirmwareRelease getNewest() {
        return releasesDesc.size() > 0 ? releasesDesc.get(0) : null;
    }

    public boolean isUpdateRequired(FirmwareVersion deviceVersion) {
        if (!deviceVersion.isValid())
            return false;

        for (FirmwareRelease r : releasesDesc) {
            if (!r.version.isNewerThan(deviceVersion))
                return false;

            if (r.required)
                return true;
        }
        return false;
    }
} public static class FirmwareVersion implements Comparable<FirmwareVersion> {
    public static final FirmwareVersion INVALID = new FirmwareVersion(0, 0, 0);

    public final int major;
    public final int minor;
    public final int patch;

    public static FirmwareVersion create(Features features) {
        if (features.getBootloaderMode()) {
            return (features.hasFwMajor() && features.hasFwMinor() && features.hasFwPatch() && features.getFwMajor() > 0) ?
                    new FirmwareVersion(features.getFwMajor(), features.getFwMinor(), features.getFwPatch()) : FirmwareVersion.INVALID;
        }
        else
            return new FirmwareVersion(features.getMajorVersion(), features.getMinorVersion(), features.getPatchVersion());
    }

    public FirmwareVersion(int major, int minor, int patch) {
        this.major = major;
        this.minor = minor;
        this.patch = patch;
    }

    public boolean isValid() {
        return major != 0 || minor != 0 || patch != 0;
    }

    public boolean isNewerThan(FirmwareVersion v) {
        return compareTo(v) > 0;
    }

    @Override
    public int compareTo(@NonNull FirmwareVersion v) {
        if (this.major != v.major)
            return this.major < v.major ? -1 : 1;
        else if (this.minor != v.minor)
            return this.minor < v.minor ? -1 : 1;
        else if (this.patch != v.patch)
            return this.patch < v.patch ? -1 : 1;
        else
            return 0;
    }

    @Override
    public String toString() {
        return major + "." + minor + "." + patch;
    }
} public class NavDrawer {
    private static final String TAG = NavDrawer.class.getSimpleName();

    final DrawerLayout drawerLayout;
    final ScrimInsetsScrollView drawerContent;
    final View rootNavDrawerTop;
    final TextView txtNavDrawerAppTitle;
    final RadioGroup radioGroupTrezors;
    final View dividerTrezors;
    final View btnHelp;
    final View btnSupport;
    final View btnAbout;

    final boolean isPermanent;
    final GlobalContext gct;

    // State
    boolean hideDrawerOnStop = false;


    public static NavDrawer setContentView(BaseActivity activity, int contentLayout) {
        return setContentView(activity, activity.getLayoutInflater().inflate(contentLayout, null, false));
    }

    public static NavDrawer setContentView(BaseActivity activity, View contentView) {
        return new NavDrawer(activity, contentView);
    }


    private NavDrawer(final BaseActivity activity, View contentView) {
        this.isPermanent = activity.getResources().getBoolean(R.bool.nav_drawer_permanent);
        this.gct = GlobalContext.get();

        activity.setContentView(isPermanent ? R.layout.nav_drawer_permanent : R.layout.nav_drawer_hideable);
        this.drawerLayout = (DrawerLayout) activity.findViewById(isPermanent ? R.id.drawer_layout_permanent : R.id.drawer_layout_hideable);
        this.drawerContent = (ScrimInsetsScrollView)drawerLayout.findViewById(R.id.drawer_content);

        this.rootNavDrawerTop = (View)drawerContent.findViewById(R.id.root_nav_drawer_top);
        this.txtNavDrawerAppTitle = (TextView)drawerContent.findViewById(R.id.txt_nav_drawer_app_title);
        this.radioGroupTrezors = (RadioGroup)drawerContent.findViewById(R.id.radio_group_trezors);
        this.dividerTrezors = (View)drawerContent.findViewById(R.id.divider_trezors);
        this.btnHelp = (View)drawerContent.findViewById(R.id.btn_help);
        this.btnSupport = (View)drawerContent.findViewById(R.id.btn_support);
        this.btnAbout = (View)drawerContent.findViewById(R.id.btn_about);

        if (!isPermanent) {
            drawerLayout.addView(contentView, 0);
            drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, drawerContent);
        }
        else {
            ((ViewGroup) activity.findViewById(R.id.nav_drawer_screen_content)).addView(contentView);
            drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN, drawerContent);
            drawerLayout.setScrimColor(Color.TRANSPARENT);
            drawerLayout.setFocusableInTouchMode(false);
        }

        txtNavDrawerAppTitle.setText(CustomHtml.fromHtmlWithCustomSpans(CustomHtml.getTextSizeTag(activity.getString(R.string.app_name), activity.getResources().getDimensionPixelSize(R.dimen.text_subhead_large))
            + "\n" + AppUtils.getAppVersionName()));

        btnHelp.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://wiki.trezor.io/User_manual"));
                try {
                    activity.startActivity(intent);
                    hideDrawerOnStop = true;
                }
                catch (Exception ex) {
                    LogUtils.e(TAG, "btnHelp onClick threw Exception:", ex);
                    Toast.makeText(activity, R.string.err_unknown_error, Toast.LENGTH_SHORT).show();
                }
            }
        });

        btnSupport.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://trezor.io/support"));
                try {
                    activity.startActivity(intent);
                    hideDrawerOnStop = true;
                }
                catch (Exception ex) {
                    LogUtils.e(TAG, "btnSupport onClick threw Exception:", ex);
                    Toast.makeText(activity, R.string.err_unknown_error, Toast.LENGTH_SHORT).show();
                }
            }
        });

        btnAbout.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                hideDrawerOnStop = true;
                activity.startActivity(AboutActivity.createIntent(view.getContext()));
                activity.setDontDisconnectOnStop();
            }
        });


        drawerLayout.setStatusBarBackgroundColor(activity.getResources().getColor(R.color.primary_dark));
        drawerContent.setOnInsetsCallback(new OnInsetsCallback() {
            @Override
            public void onInsetsChanged(Rect insets) {
                if (rootNavDrawerTop.getPaddingTop() != insets.top) {
                    rootNavDrawerTop.setPadding(
                            rootNavDrawerTop.getPaddingLeft(),
                            insets.top,
                            rootNavDrawerTop.getPaddingRight(),
                            rootNavDrawerTop.getPaddingBottom()
                    );
                    rootNavDrawerTop.getLayoutParams().height = activity.getResources().getDimensionPixelSize(R.dimen.nav_drawer_top_height) + insets.top;
                    rootNavDrawerTop.requestLayout();
                }
            }
        });

        activity.setNavDrawerCallbacks(new INavDrawerCallbacks() {
            @Override
            public void onActivityStart() {
                hideDrawerOnStop = false;
            }

            @Override
            public void onActivityStop() {
                if (hideDrawerOnStop && !isPermanent) {
                    drawerLayout.closeDrawers();
                }
            }
        });

//        radioGroupTrezors.setOnCheckedChangeListener(new OnCheckedChangeListener() {
//            @Override
//            public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
//
//            }
//        });

        //refreshTrezorsList(); resi si napojena aktivita
    }


    public boolean getIsPermanent() {
        return isPermanent;
    }

    public void openDrawer() {
        if (!isPermanent) {
            drawerLayout.openDrawer(Gravity.LEFT);
        }
    }

    private void refreshTrezorsList() {
        ImmutableList<InitializedTrezor> trezors = gct.getCommonDb().getTrezors();
        if (radioGroupTrezors.getChildCount() > trezors.size()) {
            radioGroupTrezors.removeViews(trezors.size(), radioGroupTrezors.getChildCount() - trezors.size());
        }

        LayoutInflater inflater = LayoutInflater.from(radioGroupTrezors.getContext());
        for (int i = radioGroupTrezors.getChildCount(); i < trezors.size(); i++) {
            RadioButton btn = (RadioButton)inflater.inflate(R.layout.nav_drawer_trezor_radiobutton, radioGroupTrezors, false);
            btn.setCompoundDrawables(createNavDrawerButtonIcon(R.drawable.ic_trezor), null, null, null);
            btn.setOnClickListener(onTrezorClickListener);
            radioGroupTrezors.addView(btn);
        }

        for (int i = 0; i < trezors.size(); i++) {
            InitializedTrezor t = trezors.get(i);
            RadioButton btn = (RadioButton)radioGroupTrezors.getChildAt(i);

            btn.setText(TextUtils.isEmpty(t.getFeatures().getLabel()) ? btn.getContext().getString(R.string.init_trezor_device_label_default) : t.getFeatures().getLabel());
            int id = getTrezorButtonId(t.getFeatures().getDeviceId());
            btn.setId(id);
        }

        refreshCurrentSelectedTrezor(gct.getCommonDb().getLastSelectedDeviceId());

        radioGroupTrezors.setVisibility(trezors.isEmpty() ? View.GONE : View.VISIBLE);
        dividerTrezors.setVisibility(trezors.isEmpty() ? View.GONE : View.VISIBLE);
    }

    private void refreshCurrentSelectedTrezor(String currentSelectedTrezorDeviceId) {
        final int id = getTrezorButtonId(currentSelectedTrezorDeviceId);

        for (int i = 0; i < radioGroupTrezors.getChildCount(); i++) {
            RadioButton btn = (RadioButton)radioGroupTrezors.getChildAt(i);
            btn.setChecked(false);
        }
        for (int i = 0; i < radioGroupTrezors.getChildCount(); i++) {
            RadioButton btn = (RadioButton)radioGroupTrezors.getChildAt(i);
            if (btn.getId() == id)
                btn.setChecked(true);
        }
    }

    private Drawable createNavDrawerButtonIcon(int whiteIconBmpRid) {
        Resources res = radioGroupTrezors.getResources();
        return BitmapUtils.getColoredDrawable(res.getDrawable(whiteIconBmpRid),
                res.getColor(R.color.ic_color_darker_light),
                res.getColor(R.color.ic_color_highlight),
                android.R.attr.state_checked );

//        StateListDrawable ret = new StateListDrawable();
//        ret.addState(new int[] { android.R.attr.state_checked }, BitmapUtils.getColoredDrawable(this, whiteIconBmpRid, getResources().getColor(R.color.nav_drawer_checked_item_highlight)));
//        ret.addState(StateSet.WILD_CARD, BitmapUtils.getColoredDrawable(this, whiteIconBmpRid, getResources().getColor(R.color.ic_color_darker_light)));
        //return ret;
    }

    private static int getTrezorButtonId(String deviceId) {
        int ret = deviceId.hashCode();
        return ret == 0 || ret == -1 ? 1 : ret; // 0 a -1 radsi nepouzijeme
    }

    public final TrezorListChangedReceiver trezorListChangedReceiver = new TrezorListChangedReceiver() {
        @Override
        public void onTrezorListChanged(boolean listChanged, boolean lastSelectedDeviceIdChanged) {
            if (listChanged)
                refreshTrezorsList();
            else
                refreshCurrentSelectedTrezor(gct.getCommonDb().getLastSelectedDeviceId());
        }
    };

    private final OnClickListener onTrezorClickListener = new OnClickListener() {
        @Override
        public void onClick(View view) {
            int checkedId = view.getId();

            for (InitializedTrezor t : gct.getCommonDb().getTrezors()) {
                //noinspection ResourceType
                if (getTrezorButtonId(t.getFeatures().getDeviceId()) == checkedId) {
                    gct.getCommonDb().setLastSelectedDeviceId(t.getFeatures().getDeviceId());

                    if (!isPermanent && drawerLayout.isDrawerOpen(Gravity.LEFT)) {
                        radioGroupTrezors.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                if (!isPermanent)
                                    drawerLayout.closeDrawer(Gravity.LEFT);
                            }
                        }, 300);
                    }
                    break;
                }
            }
        }
    };

    public interface INavDrawerCallbacks {
        void onActivityStart();
        void onActivityStop();
    }
} public static class MsgWrp extends ApiParcelable {
    public final MessageType msgType;
    public final Message msg;

    public MsgWrp(Message msg) {
        this.msgType = MessageType.valueOf("MessageType_" + msg.getClass().getSimpleName());
        this.msg = msg;
    }

    public MsgWrp(ApiDataInput d) {
        this.msgType = MessageType.valueOf(d.readString());
        try {
            this.msg = TrezorManager.parseMessageFromBytes(msgType, d.readBytes());
        } catch (InvalidProtocolBufferException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void save(ApiDataOutput d, int flags) {
        d.write(this.msgType.name());
        d.write(msg.toByteArray());
    }

    public static final ApiCreator<MsgWrp> CREATOR = new ApiCreator<MsgWrp>() {
        public MsgWrp create(ApiDataInput d) { return new MsgWrp(d); }
        public MsgWrp[] newArray(int size) { return new MsgWrp[size]; }
    };
} public static class TrezorError extends TaskError {
    public static final TrezorError ERR_NOT_CONNECTED = new TrezorError(TrezorException.TYPE_NOT_CONNECTED, R.string.trezor_err_not_connected);
    public static final TrezorError ERR_NEEDS_PERMISSION = new TrezorError(TrezorException.TYPE_NEEDS_PERMISSION, R.string.trezor_err_needs_permission);
    public static final TrezorError ERR_COMMUNICATION_ERROR = new TrezorError(TrezorException.TYPE_COMMUNICATION_ERROR, R.string.trezor_err_communication_error);
    public static final TrezorError ERR_UNEXPECTED_RESPONSE = new TrezorError(TrezorException.TYPE_UNEXPECTED_RESPONSE, R.string.trezor_err_unexpected_response);
    // POZOR pri pridavani nezapominat pridavat case radky do tryGetTrezorError()

    private static TrezorError tryGetTrezorError(int type) {
        switch (type) {
            case TrezorException.TYPE_NOT_CONNECTED: return ERR_NOT_CONNECTED;
            case TrezorException.TYPE_NEEDS_PERMISSION: return ERR_NEEDS_PERMISSION;
            case TrezorException.TYPE_COMMUNICATION_ERROR: return ERR_COMMUNICATION_ERROR;
            case TrezorException.TYPE_UNEXPECTED_RESPONSE: return ERR_UNEXPECTED_RESPONSE;
            default: return null;
        }
    }


    private final int type;
    private final int msgRid;

    public static ITaskError getErrorFromException(TrezorException ex) {
        TrezorError res = tryGetTrezorError(ex.getType());
        return res != null ? res : BaseError.ERR_UNKNOWN_ERROR;
    }

    // private!
    private TrezorError(int type, int msgRid) {
        this.type = type;
        this.msgRid = msgRid;
    }

    @Override
    public void save(ApiDataOutput d, int flags) {
        d.write(this.type);
    }

    public int getType() {
        return this.type;
    }

    public int getMsgRid() {
        return this.msgRid;
    }

    @Override
    public int hashCode() {
        int _hash = 17;
        _hash = _hash * 29 + type;
        _hash = _hash * 29 + msgRid;
        return _hash;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

        if (!(o instanceof TrezorError)) {
            return false;
        }

        TrezorError lhs = (TrezorError) o;
        return lhs != null &&
                type == lhs.type &&
                msgRid == lhs.msgRid;
    }

    @Override
    public CharSequence getMsg(ITaskContext context) {
        return context.getAndroidContext().getString(msgRid);
    }

    @Override
    public String getGoogleAnalyticsId() {
        return "TrezorError:" + type;
    }

    // upraveno!
    public static final ApiCreator<TrezorError> CREATOR = new ApiCreator<TrezorError>() {
        public TrezorError create(ApiDataInput d) {
            TrezorError ret = tryGetTrezorError(d.readInt());
            if (ret == null)
                throw new IllegalStateException();
            return ret;
        }

        public TrezorError[] newArray(int size) { return new TrezorError[size]; }
    };
} public static class TrezorTaskParam extends TaskParam implements ITrezorTaskParam {
    private final MsgWrp msgParam;
    private final IApiParcelable tag; // abstract optional

    public TrezorTaskParam(Message msg) {
        this(new MsgWrp(msg), null);
    }

    public TrezorTaskParam(Message msg, IApiParcelable tag) {
        this(new MsgWrp(msg), tag);
    }

    public TrezorTaskParam(MsgWrp msgParam, IApiParcelable tag) {
        this.msgParam = msgParam;
        this.tag = tag;
    }

    public TrezorTaskParam(ApiDataInput d) {
        this.msgParam = d.readObject(MsgWrp.CREATOR);
        this.tag = d.readOptParcelableWithName();
    }

    @Override
    public void save(ApiDataOutput d, int flags) {
        d.write(this.msgParam, flags);
        d.writeOpt(this.tag, flags);
    }

    public MsgWrp getMsgParam() {
        return this.msgParam;
    }

    public IApiParcelable getTag() {
        return this.tag;
    }

    @Override
    public int describeContents() {
        return ApiParcelable.baseDescribeContents();
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        ApiParcelable.baseWriteToParcel(this, parcel, i);
    }

    @Override
    public String getSerialExecutionKey(ITaskContext context) {
        return SERIAL_EXECUTION_KEY_TREZOR;
    }

    @Override
    public boolean isExecutionInParallelForbidden(ITaskContext context) {
        return true;
    }

    @Override
    public TrezorTaskResult createResultUncached(ITaskContext context, ITask task) throws TaskException {
        try {
            GlobalContext gct = (GlobalContext)context;
            TrezorManager t = gct.getTrezorManager();

            if (!t.tryConnectDevice()) {
                return createErrorResult(context, task, t.hasDeviceWithoutPermission(false) ? TrezorError.ERR_NEEDS_PERMISSION : TrezorError.ERR_NOT_CONNECTED);
            }
            else {
                MsgWrp msgResult = new MsgWrp(t.sendMessage(msgParam.msg));
                return new TrezorTaskResult(this, BaseError.ERR_OK, msgResult);
            }
        }
        catch (TrezorException ex) {
            return createErrorResult(context, task, TrezorError.getErrorFromException(ex));
        }
    }

    @Override
    public TrezorTaskResult createErrorResult(ITaskContext context, ITask task, ITaskError error) {
        return new TrezorTaskResult(this, error, null);
    }

    public static final ApiCreator<TrezorTaskParam> CREATOR = new ApiCreator<TrezorTaskParam>() {
        public TrezorTaskParam create(ApiDataInput d) { return new TrezorTaskParam(d); }
        public TrezorTaskParam[] newArray(int size) { return new TrezorTaskParam[size]; }
    };
} public static class TrezorTaskResult extends TaskResult<TrezorTaskParam> implements ITrezorTaskResult {
    private final MsgWrp msgResult;

    public TrezorTaskResult(TrezorTaskParam param, ITaskError error, MsgWrp msgResult) {
        super(param, error);
        this.msgResult = msgResult;
    }

    public TrezorTaskResult(ApiDataInput d) {
        super(d.<TrezorTaskParam>readParcelableWithName(), d.<ITaskError>readParcelableWithName());

        if (isValidResult()) {
            this.msgResult = d.readObject(MsgWrp.CREATOR);
        }
        else {
            this.msgResult = null;
        }

    }

    @Override
    public void save(ApiDataOutput d, int flags) {
        d.writeWithName(getParam(), flags);
        d.writeWithName(getError(), flags);

        if (isValidResult()) {
            d.write(this.msgResult, flags);
        }
    }

    public MsgWrp getMsgResult() {
        return this.msgResult;
    }

    @Override
    public int describeContents() {
        return ApiParcelable.baseDescribeContents();
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        ApiParcelable.baseWriteToParcel(this, parcel, i);
    }

    @Override
    public boolean isCacheableResult() {
        return false;
    }

    public static final ApiCreator<TrezorTaskResult> CREATOR = new ApiCreator<TrezorTaskResult>() {
        public TrezorTaskResult create(ApiDataInput d) { return new TrezorTaskResult(d); }
        public TrezorTaskResult[] newArray(int size) { return new TrezorTaskResult[size]; }
    };
}     public static class InitializedTrezor extends ApiParcelable {
        private final Features features;
        //private final PublicKey publicKey;

        public InitializedTrezor(Features features/*, PublicKey publicKey*/) {
            this.features = features;
            //this.publicKey = publicKey;
        }

        public InitializedTrezor(ApiDataInput d) {
            try {
                this.features = (Features) TrezorManager.parseMessageFromBytes(MessageType.MessageType_Features, d.readBytes());
                //this.publicKey = (PublicKey)TrezorManager.parseMessageFromBytes(MessageType.MessageType_PublicKey, d.readBytes());
            } catch (InvalidProtocolBufferException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public void save(ApiDataOutput d, int flags) {
            d.write(features.toByteArray());
            //d.write(publicKey.toByteArray());
        }

        public Features getFeatures() {
            return this.features;
        }

//        public PublicKey getPublicKey() {
//            return this.publicKey;
//        }

        public static final ApiCreator<InitializedTrezor> CREATOR = new ApiCreator<InitializedTrezor>() {
            public InitializedTrezor create(ApiDataInput d) { return new InitializedTrezor(d); }
            public InitializedTrezor[] newArray(int size) { return new InitializedTrezor[size]; }
        };
    } public static abstract class TrezorListChangedReceiver extends BaseLocalReceiver {
    private static final String ACTION = TrezorListChangedReceiver.class.getName() + ".ACTION";

    public TrezorListChangedReceiver() {
        super(ACTION);
    }

    public static void sendBroadcast(Context context, boolean listChanged, boolean lastSelectedDeviceIdChanged) {
        Intent intent = new Intent(ACTION)
                .putExtra("listChanged", listChanged)
                .putExtra("lastSelectedDeviceIdChanged", lastSelectedDeviceIdChanged);
        sendBroadcast(context, intent);
    }

    @Override
    public void onReceiveRegistered(Context context, Intent intent) {
        onTrezorListChanged(
                intent.getBooleanExtra("listChanged", false),
                intent.getBooleanExtra("lastSelectedDeviceIdChanged", false)
        );
    }

    /**
     * @param listChanged - pokud doslo ke zmene v samotnem seznamu (pridani/odebrani), nebo doslo ke zmene labelu nektereho trezoru
     * @param lastSelectedDeviceIdChanged
     */
    public abstract void onTrezorListChanged(boolean listChanged, boolean lastSelectedDeviceIdChanged);
} public class CheckConfirmedDialog extends BaseDialogFragment {
    public static final String DEFAULT_FRAGMENT_TAG = CheckConfirmedDialog.class.getName();
    
    private static final String BUNDLE_ID = "CheckConfirmedDialog.id";
    private static final String BUNDLE_TITLE = "CheckConfirmedDialog.title";
    private static final String BUNDLE_MESSAGE = "CheckConfirmedDialog.message";
    private static final String BUNDLE_CHECK_TEXT = "EnterTextDialog.checkText";
    private static final String BUNDLE_CONFIRM_TEXT = "EnterTextDialog.confirmText";
    
    private String id;
    private CheckBox checkBox;
    private Button btnOk;

    public static CheckConfirmedDialog show(FragmentManager fm, DialogFragment oldDialog, String fragmentTagOpt, String id, CharSequence title, CharSequence message, CharSequence checkText, CharSequence confirmText) {
        Bundle b = new Bundle();
        b.putString(BUNDLE_ID, id);
        b.putCharSequence(BUNDLE_TITLE, title);
        b.putCharSequence(BUNDLE_MESSAGE, message);
        b.putCharSequence(BUNDLE_CHECK_TEXT, checkText);
        b.putCharSequence(BUNDLE_CONFIRM_TEXT, confirmText);
        CheckConfirmedDialog ret = new CheckConfirmedDialog();
        ret.setArguments(b);
        ret.setCancelable(true);
        return FragmentUtils.showDialogRemoveOldOne(fm, oldDialog, ret, fragmentTagOpt == null ? DEFAULT_FRAGMENT_TAG : fragmentTagOpt);
    }
    
    @Override
    protected Builder build(Builder b, Bundle savedInstanceState) {
        Bundle a = getArguments();
        this.id = getArguments().getString(BUNDLE_ID);
        
        CharSequence title = a.getCharSequence(BUNDLE_TITLE);
        if (!TextUtils.isEmpty(title))
            b.setTitle(title); 

        CharSequence confirmText = a.getCharSequence(BUNDLE_CONFIRM_TEXT);
        b.setPositiveButton(TextUtils.isEmpty(confirmText) ? getString(android.R.string.ok) : confirmText, new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (checkBox.isChecked()) {
                    onCheckConfirmedDialogDone(id, false);
                    dismiss();
                }
            }
        });
        b.setNegativeButton(R.string.cancel, new OnClickListener() {
            @Override
            public void onClick(View v) {
                onCheckConfirmedDialogDone(id, true);
                dismiss();
            }
        });
        
        View view = getActivity().getLayoutInflater().inflate(R.layout.check_confirmed_dialog, null);
        TextView text = (TextView)view.findViewById(R.id.text);
        this.checkBox = (CheckBox) view.findViewById(R.id.checkbox);
        
        CharSequence message = getArguments().getCharSequence(BUNDLE_MESSAGE);
        if (TextUtils.isEmpty(message))
            text.setVisibility(View.GONE);
        else {
            text.setVisibility(View.VISIBLE);
            text.setText(message);
            text.setMovementMethod(LinkMovementMethod.getInstance());
        }

        CharSequence checkText = a.getCharSequence(BUNDLE_CHECK_TEXT);
        this.checkBox.setText(TextUtils.isEmpty(checkText) ? getString(R.string.i_understand) : checkText);
        this.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (btnOk != null)
                    btnOk.setEnabled(b);
            }
        });
        
        b.setView(view);
        return b;
    }

    @Override
    public void onStart() {
        super.onStart();
        
        this.btnOk = (Button)getDialog().findViewById(android.R.id.button1);
        if (btnOk != null) {
            btnOk.setEnabled(checkBox.isChecked());
        }
    }
    
    @Override
    public void onCancel(DialogInterface dialog) {
        super.onCancel(dialog);
        onCheckConfirmedDialogDone(getArguments().getString(BUNDLE_ID), true);
    }
    
    protected void onCheckConfirmedDialogDone(String id, boolean canceled) {
        if (this.getTargetFragment() != null) {
            ((OnCheckConfirmedDialogDone)this.getTargetFragment()).onCheckConfirmedDialogDone(id, canceled);
        }
        else {
            ((OnCheckConfirmedDialogDone)this.getActivity()).onCheckConfirmedDialogDone(id, canceled);
        }
    }
    
    public interface OnCheckConfirmedDialogDone {
        void onCheckConfirmedDialogDone(String id, boolean canceled);
    }
} public interface OnCheckConfirmedDialogDone {
    void onCheckConfirmedDialogDone(String id, boolean canceled);
} public class EnterTextDialog extends BaseDialogFragment {
    public static final String DEFAULT_FRAGMENT_TAG = EnterTextDialog.class.getName();
    
    private static final String BUNDLE_ID = "EnterTextDialog.id";
    private static final String BUNDLE_TITLE = "EnterTextDialog.title";
    private static final String BUNDLE_MESSAGE = "EnterTextDialog.message";
    private static final String BUNDLE_HINT = "EnterTextDialog.hint";
    private static final String BUNDLE_DEF_TEXT = "EnterTextDialog.defText";
    
    private String id;
    private EditText editText;
    private Button btnOk;

    public static EnterTextDialog show(FragmentManager fm, DialogFragment oldDialog, String fragmentTagOpt, String id,
                                       CharSequence title, CharSequence message, CharSequence hint, String defText)
    {
        Bundle b = new Bundle();
        b.putString(BUNDLE_ID, id);
        b.putCharSequence(BUNDLE_TITLE, title);
        b.putCharSequence(BUNDLE_MESSAGE, message);
        b.putCharSequence(BUNDLE_HINT, hint);
        b.putString(BUNDLE_DEF_TEXT, defText);
        EnterTextDialog ret = new EnterTextDialog();
        ret.setArguments(b);
        ret.setCancelable(true);
        return FragmentUtils.showDialogRemoveOldOne(fm, oldDialog, ret, fragmentTagOpt == null ? DEFAULT_FRAGMENT_TAG : fragmentTagOpt);
    }
    
    @Override
    protected Builder build(Builder b, Bundle savedInstanceState) {
        Bundle a = getArguments();
        this.id = getArguments().getString(BUNDLE_ID);
        
        CharSequence title = a.getCharSequence(BUNDLE_TITLE);
        if (!TextUtils.isEmpty(title))
            b.setTitle(title); 
        
        b.setPositiveButton(R.string.confirm, new OnClickListener() {
            @Override
            public void onClick(View v) {
                onEnterTextDialogDone(id, false, editText.getText().toString());
                dismiss();
            }
        });
        b.setNegativeButton(R.string.cancel, new OnClickListener() {
            @Override
            public void onClick(View v) {
                onEnterTextDialogDone(id, true, null);
                dismiss();
            }
        });
        
        View view = getActivity().getLayoutInflater().inflate(R.layout.enter_text_dialog, null);
        TextView text = (TextView)view.findViewById(R.id.text);
        this.editText = (EditText)view.findViewById(R.id.edit_text);
        
        CharSequence message = getArguments().getCharSequence(BUNDLE_MESSAGE);
        if (TextUtils.isEmpty(message))
            text.setVisibility(View.GONE);
        else {
            text.setVisibility(View.VISIBLE);
            text.setText(message);
        }
        
        this.editText.setHint(getArguments().getCharSequence(BUNDLE_HINT));
        
        b.setView(view);
        
        if (savedInstanceState != null) {
            this.editText.setText(savedInstanceState.getString(BUNDLE_DEF_TEXT));
        }
        else {
            this.editText.setText(getArguments().getString(BUNDLE_DEF_TEXT));
            this.editText.setSelection(0, editText.getText().length());
        }
        
        this.editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (btnOk != null) {
                    btnOk.setEnabled(editText.getText().length() > 0);
                }
            }
            
            public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
            public void afterTextChanged(Editable s) { }
        });
        return b;
    }
    
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog ret = super.onCreateDialog(savedInstanceState);
        ret.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
        return ret;
    }
    
    @Override
    public void onStart() {
        super.onStart();
        
        this.btnOk = (Button)getDialog().findViewById(android.R.id.button1);
        if (btnOk != null) {
            btnOk.setEnabled(editText.getText().length() > 0);
        }
    }
    
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(BUNDLE_DEF_TEXT, editText.getText().toString());
    }
    
    @Override
    public void onCancel(DialogInterface dialog) {
        super.onCancel(dialog);
        onEnterTextDialogDone(getArguments().getString(BUNDLE_ID), true, null);
    }
    
    protected void onEnterTextDialogDone(String id, boolean canceled, String text) {
        if (this.getTargetFragment() != null) {
            ((OnEnterTextDialogDone)this.getTargetFragment()).onEnterTextDialogDone(id, canceled, text);
        }
        else {
            ((OnEnterTextDialogDone)this.getActivity()).onEnterTextDialogDone(id, canceled, text);
        }
    }
    
    public interface OnEnterTextDialogDone {
        void onEnterTextDialogDone(String id, boolean canceled, String text);
    }
} public interface OnEnterTextDialogDone {
    void onEnterTextDialogDone(String id, boolean canceled, String text);
} public class CustomHtml {	
    public static final char HARD_SPACE = (char)0xf00a0;
    public static final String TAG_LINE_BREAK = "<BR />";
    
	protected static final String SPAN_TAG = "span";
    protected static final String SPAN_ATTR_TYPE_NAME = "class";

    protected static final String SPAN_ATTR_TYPE_SIZE = "size";
    protected static final String SPAN_ATTR_SIZE_VALUE = "size";

    protected static final String SPAN_ATTR_TYPE_RELATIVE_SIZE = "rltsz";

	private static Typeface boldTypeface;

	public static Typeface getBoldTypeface(Context context) {
		if (boldTypeface == null) {
			boldTypeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD);
		}
		return boldTypeface;
	}

	public static String getHardSpaces2(int count) {
        StringBuilder ret = new StringBuilder();
        for (int i = 0; i < count; i++) {
            ret.append(i == count - 1 ? " " : HARD_SPACE);
        }
        return ret.toString();
    }

	public static String getFontColorTag(String text, int color) {
		return "<font color=\"" + ColorUtils.getHtmlColor(color) + "\">" + text + "</font>";
	}

    public static String getTextSizeTag(String s, int textSizePx) {
        return "<" + SPAN_TAG + " " + SPAN_ATTR_TYPE_NAME + "=\"" + SPAN_ATTR_TYPE_SIZE + "\" " + SPAN_ATTR_SIZE_VALUE + "=\"" + textSizePx + "\">" + s + "</" + SPAN_TAG + ">";
    }

    public static String getRelativeTextSizeTag(String s, float proportion) {
        return "<" + SPAN_TAG + " " + SPAN_ATTR_TYPE_NAME + "=\"" + SPAN_ATTR_TYPE_RELATIVE_SIZE + "\" " + SPAN_ATTR_SIZE_VALUE + "=\"" + (int)(proportion * 100) + "\">" + s + "</" + SPAN_TAG + ">";
    }
	
	public static String getBoldTag(String text) {
	    return "<b>" + text + "</b>";
	}
	
	public static String getImgTag(String srcAttr) {
	    return "<img src=\"" + srcAttr + "\" />";
	}

	
	public static Spanned fromHtmlWithCustomSpans(String source) {
		return fromHtmlWithCustomSpans(source, null);
	}
	
	public static Spanned fromHtmlWithCustomSpans(String source, Html.ImageGetter imageGetter) {
		return fromHtmlWithCustomSpans(source, imageGetter, (Html.TagHandler)null);
	}


	public static Spanned fromHtmlWithCustomSpans(String source, Html.ImageGetter imageGetter, Html.TagHandler tagHandler) {
		if (source.indexOf('\n') >= 0) {
		    source = source.replace("\n", TAG_LINE_BREAK);
		}
		
		return SpannedString.valueOf(Html.fromHtml(source, imageGetter, new CustomTagHandler(tagHandler)));
	}



	
	public static class CustomTagHandler implements TagHandler {
		protected final Context context;
		private final TagHandler providedTagHandler;
		protected final Stack<IHtmlTagSpan> spansStack = new Stack<IHtmlTagSpan>();
		
		public CustomTagHandler(TagHandler providedTagHandler) {
			this.context = GlobalContext.get().getAndroidContext();
			this.providedTagHandler = providedTagHandler;
		}
		
		public boolean handleStartTag(String tag, Attributes attributes, Editable output, XMLReader xmlReader) {
			if (tag.equalsIgnoreCase(SPAN_TAG)) {
                String type = attributes.getValue("", SPAN_ATTR_TYPE_NAME);
                if (handleSpanStartTag(type, attributes, output))
                    return true;
                else {
                    spansStack.push(null);
                    return this.providedTagHandler != null && this.providedTagHandler.handleStartTag(tag, attributes, output, xmlReader);
                }
			}
			else {
				return this.providedTagHandler != null && this.providedTagHandler.handleStartTag(tag, attributes, output, xmlReader);
			}
		}

		public boolean handleEndTag(String tag, Editable output, XMLReader xmlReader) {
			if (tag.equalsIgnoreCase(SPAN_TAG)) {
				IHtmlTagSpan spanTag = spansStack.pop();
				if (handleSpanEndTag(spanTag, output))
                    return true;
                else if (spanTag == null) {
                    return this.providedTagHandler != null && this.providedTagHandler.handleEndTag(tag, output, xmlReader);
                }
                else
					throw new RuntimeException();
			}
			else {
				return this.providedTagHandler != null && this.providedTagHandler.handleEndTag(tag, output, xmlReader);
			}
		}


        protected boolean handleSpanStartTag(String type, Attributes attributes, Editable output) {
            if (SPAN_ATTR_TYPE_SIZE.equalsIgnoreCase(type)) {
                spansStack.push(processSizeStart(output, attributes));
                return true;
            }
            else if (SPAN_ATTR_TYPE_RELATIVE_SIZE.equalsIgnoreCase(type)) {
                spansStack.push(processRelativeSizeStart(output, attributes));
                return true;
            }
            else
                return false;
        }

        protected boolean handleSpanEndTag(IHtmlTagSpan spanTag, Editable output) {
            if (spanTag instanceof AbsoluteSizeSpan) {
                processSizeEnd(output);
                return true;
            }
            else if (spanTag instanceof RelativeSizeSpan) {
                processRelativeSizeEnd(output);
                return true;
            }
            else
                return false;
        }


        private AbsoluteSizeSpan processSizeStart(Editable output, Attributes attributes) {
            int len = output.length();
            AbsoluteSizeSpan ret = new AbsoluteSizeSpan(Integer.parseInt(attributes.getValue("", SPAN_ATTR_SIZE_VALUE)));
            output.setSpan(ret, len, len, Spannable.SPAN_MARK_MARK);
            return ret;
        }

        private void processSizeEnd(Editable output) {
            int len = output.length();
            Object obj = getLast(output, AbsoluteSizeSpan.class);
            int where = output.getSpanStart(obj);

            output.removeSpan(obj);

            if (where != len) {
                output.setSpan(obj, where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }


        private RelativeSizeSpan processRelativeSizeStart(Editable output, Attributes attributes) {
            int len = output.length();
            RelativeSizeSpan ret = new RelativeSizeSpan(((float) Integer.parseInt(attributes.getValue("", SPAN_ATTR_SIZE_VALUE)) / 100));
            output.setSpan(ret, len, len, Spannable.SPAN_MARK_MARK);
            return ret;
        }

        private void processRelativeSizeEnd(Editable output) {
            int len = output.length();
            Object obj = getLast(output, RelativeSizeSpan.class);
            int where = output.getSpanStart(obj);

            output.removeSpan(obj);

            if (where != len) {
                output.setSpan(obj, where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }


	    protected Object getLast(Editable text, @SuppressWarnings("rawtypes") Class kind) {
	        @SuppressWarnings("unchecked")
			Object[] objs = text.getSpans(0, text.length(), kind);

	        if (objs.length == 0) {
	            return null;
	        } else {
	            for(int i = objs.length;i>0;i--) {
	                if(text.getSpanFlags(objs[i-1]) == Spannable.SPAN_MARK_MARK) {
	                    return objs[i-1];
	                }
	            }
	            return null;
	        }
	    }
	}
} public class CommonUtils {
    public static boolean isTrezorV2(Features features) {
        return TextUtils.equals(features.getModel(), "T");
    }
}
 public class CustomActionBar extends Toolbar {
    public CustomActionBar(Context context) {
        this(context, null);
    }

    public CustomActionBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomActionBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    public static CustomActionBar setContentView(BaseActivity activity, int contentLayout, boolean withUpButton) {
        Couple<ViewGroup, CustomActionBar> c = inflateWithActionBar(activity, contentLayout);
        activity.setContentView(c.getFirst());

        if (withUpButton) {
            setNavigationButtonUp(activity);
        }

        return c.getSecond();
    }

    public static Couple<ViewGroup, CustomActionBar> inflateWithActionBar(BaseActivity activity, int contentLayout) {
        ViewGroup root = (ViewGroup) activity.getLayoutInflater().inflate(R.layout.activity_with_action_bar, null);
        CustomActionBar actionBar = (CustomActionBar)root.findViewById(R.id.action_bar);
        activity.setSupportActionBar(actionBar);
        activity.getLayoutInflater().inflate(contentLayout, root);
        return new Couple<>(root, actionBar);
    }

    public static void setNavigationButtonUp(BaseActivity activity) {
        activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        activity.getSupportActionBar().setDisplayShowHomeEnabled(true);
    }

    public void setNavigationButtonNavDrawer(final NavDrawer navDrawer) {
        setNavigationIcon(getResources().getDrawable(R.drawable.ic_navigation_drawer_white));
        setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                navDrawer.openDrawer();
            }
        });
    }

//    public void initWithoutUpButton(BaseActivity activity) {
//        activity.setSupportActionBar(this);
//        activity.getSupportActionBar().setDisplayShowHomeEnabled(false);
//    }
//
//    public void initWithUpButton(BaseActivity activity) {
//        activity.setSupportActionBar(this);
//        activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
//        activity.getSupportActionBar().setDisplayShowHomeEnabled(true);
//    }
//
//    public void initWithNavDrawerIcon(BaseActivity activity, final NavDrawer navDrawer) {
//        activity.setSupportActionBar(this);
//        activity.getSupportActionBar().setDisplayHomeAsUpEnabled(false);
//
//        if (navDrawer.getIsPermanent()) {
//            activity.getSupportActionBar().setDisplayShowHomeEnabled(false);
//        }
//        else {
//            activity.getSupportActionBar().setDisplayShowHomeEnabled(true);
//
//            //collapsingToolbarLayout.setTitle(R.);
//            Drawable icNavDrawer = DrawableCompat.wrap(getResources().getDrawable(R.drawable.ic_menu_black_24dp)).mutate();
//            DrawableCompat.setTint(icNavDrawer, Color.WHITE);
//
//            setNavigationIcon(icNavDrawer);
//            setNavigationOnClickListener(new View.OnClickListener() {
//                @Override
//                public void onClick(View view) {
//                    navDrawer.openDrawer();
//                }
//            });
//        }
//    }
} public static abstract class UsbPermissionReceiver extends BaseBroadcastReceivers.BaseGlobalReceiver {
    public static final String ACTION = UsbPermissionReceiver.class.getName() + ".ACTION";

    public UsbPermissionReceiver() {
        super(ACTION);
    }

    @Override
    protected final void onReceiveRegistered(Context context, Intent intent) {
        boolean granted = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);
        onUsbPermissionResult(granted);
    }

    public abstract void onUsbPermissionResult(boolean granted);
}
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.widget.SwitchCompat;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.circlegate.liban.base.ApiBase.ApiCreator;
import com.circlegate.liban.base.ApiBase.ApiParcelable;
import com.circlegate.liban.base.ApiDataIO.ApiDataInput;
import com.circlegate.liban.base.ApiDataIO.ApiDataOutput;
import com.circlegate.liban.base.CommonClasses.Couple;
import com.circlegate.liban.base.Exceptions.NotImplementedException;
import com.circlegate.liban.dialog.PromptDialog;
import com.circlegate.liban.dialog.PromptDialog.OnPromptDialogDone;
import com.circlegate.liban.task.TaskErrors.BaseError;
import com.circlegate.liban.task.TaskErrors.ITaskError;
import com.circlegate.liban.utils.ActivityUtils;
import com.circlegate.liban.utils.EqualsUtils;
import com.circlegate.liban.utils.LogUtils;
import com.circlegate.liban.utils.ViewUtils;
import com.google.protobuf.ByteString;
import com.satoshilabs.trezor.app.R;
import com.satoshilabs.trezor.app.activity.ChangeHomescreenActivity.ChangeHomescreenActivityResult;
import com.satoshilabs.trezor.app.activity.base.BaseActivity;
import com.satoshilabs.trezor.app.common.GlobalContext;
import com.satoshilabs.trezor.app.common.GlobalContext.FirmwareRelease;
import com.satoshilabs.trezor.app.common.GlobalContext.FirmwareReleases;
import com.satoshilabs.trezor.app.common.GlobalContext.FirmwareVersion;
import com.satoshilabs.trezor.app.common.NavDrawer;
import com.satoshilabs.trezor.app.common.TrezorTasks.MsgWrp;
import com.satoshilabs.trezor.app.common.TrezorTasks.TrezorError;
import com.satoshilabs.trezor.app.common.TrezorTasks.TrezorTaskParam;
import com.satoshilabs.trezor.app.common.TrezorTasks.TrezorTaskResult;
import com.satoshilabs.trezor.app.db.CommonDb.InitializedTrezor;
import com.satoshilabs.trezor.app.db.CommonDb.TrezorListChangedReceiver;
import com.satoshilabs.trezor.app.dialog.CheckConfirmedDialog;
import com.satoshilabs.trezor.app.dialog.CheckConfirmedDialog.OnCheckConfirmedDialogDone;
import com.satoshilabs.trezor.app.dialog.EnterTextDialog;
import com.satoshilabs.trezor.app.dialog.EnterTextDialog.OnEnterTextDialogDone;
import com.satoshilabs.trezor.app.style.CustomHtml;
import com.satoshilabs.trezor.app.utils.CommonUtils;
import com.satoshilabs.trezor.app.view.CustomActionBar;
import com.satoshilabs.trezor.lib.TrezorManager.UsbPermissionReceiver;
import com.satoshilabs.trezor.lib.protobuf.TrezorMessage.ApplySettings;
import com.satoshilabs.trezor.lib.protobuf.TrezorMessage.ButtonAck;
import com.satoshilabs.trezor.lib.protobuf.TrezorMessage.ChangePin;
import com.satoshilabs.trezor.lib.protobuf.TrezorMessage.Failure;
import com.satoshilabs.trezor.lib.protobuf.TrezorMessage.Features;
import com.satoshilabs.trezor.lib.protobuf.TrezorMessage.Initialize;
import com.satoshilabs.trezor.lib.protobuf.TrezorMessage.MessageType;
import com.satoshilabs.trezor.lib.protobuf.TrezorMessage.WipeDevice;

        btnLaunchWebwallet.setText(R.string.main_activity_launch_webwallet);
        btnChangeLabel.setText(R.string.main_activity_change_label);
        btnChangeHomescreen.setText(R.string.main_activity_change_homescreen);
        txtSecuritySetup.setText(R.string.main_activity_security_setup);
        switchPin.text.setText(R.string.main_activity_pin);
        btnChangePin.setText(R.string.main_activity_change_pin);
        setupTwoLinesText(switchPassphrase.text, R.string.main_activity_passphrase_title, R.string.main_activity_passphrase_text);
        txtDeviceSetup.setText(R.string.main_activity_device_setup);
        btnFirmwareVersion.setText(R.string.main_activity_firmware_version);
        //setupTwoLinesText(btnForgetDevice, R.string.main_activity_forget_device_title, R.string.main_activity_forget_device_text);
        setupTwoLinesText(btnWipeDevice, R.string.main_activity_wipe_device_title, R.string.main_activity_wipe_device_text);

        btnLaunchWebwallet.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    String urlString = "https://beta-wallet.trezor.io";
                    String browserPackage = "com.android.chrome";
                    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(urlString));
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    intent.setPackage(browserPackage);
                    try {
                        startActivity(intent);
                    } catch (android.content.ActivityNotFoundException ex) {
                        // Chrome not installed
                        try {
                            startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + browserPackage)));
                        } catch (android.content.ActivityNotFoundException anfe) {
                            startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + browserPackage)));
                        }
                    }
                }
                catch (Exception ex) {
                    LogUtils.e(TAG, "btnLaunchWebwallet onClick thrown exception", ex);
                    BaseError.ERR_UNKNOWN_ERROR.showToast(gct);
                }
//                if (initializedTrezor != null) {
//                    startActivity(XpubActivity.createIntent(view.getContext(), initializedTrezor.getPublicKey().getXpub()));
//                }
            }
        });
        btnChangeLabel.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (initializedTrezor != null && initializedTrezor.getFeatures().getDeviceId().equals(connectedTrezorDeviceId)) {
                    EnterTextDialog.show(getSupportFragmentManager(), null, DIALOG_CHANGE_LABEL, DIALOG_CHANGE_LABEL,
                            getString(R.string.main_activity_change_label),
                            getString(R.string.main_activity_change_label_prompt),
                            getString(R.string.init_trezor_device_label_hint),
                            "");
                }
            }
        });
        btnChangeHomescreen.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (initializedTrezor != null && initializedTrezor.getFeatures().getDeviceId().equals(connectedTrezorDeviceId)) {
                    startActivityForResult(ChangeHomescreenActivity.createIntent(view.getContext(), initializedTrezor.getFeatures().getLabel(), TextUtils.equals(initializedTrezor.getFeatures().getModel(), "T")), GlobalContext.RQC_PICK_HOMESCREEN);
                    setDontDisconnectOnStop();
                }
            }
        });
        switchPin.button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (initializedTrezor != null && initializedTrezor.getFeatures().getDeviceId().equals(connectedTrezorDeviceId)) {
                    if (initializedTrezor.getFeatures().getPinProtection()) {
                        CheckConfirmedDialog.show(getSupportFragmentManager(), null, DIALOG_DISABLE_PIN, DIALOG_DISABLE_PIN,
                                getString(R.string.warning),
                                getString(R.string.main_activity_disable_pin_prompt),
                                getString(R.string.i_understand),
                                getString(R.string.main_activity_disable_pin));
                    }
                    else {
                        executeTrezorTaskIfCan(TASK_CHANGE_SETTING_PREFIX + POSTFIX_COMMON, ChangePin.newBuilder().build());
                        refreshGui();
                    }
                }
            }
        });
        btnChangePin.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (initializedTrezor != null && initializedTrezor.getFeatures().getDeviceId().equals(connectedTrezorDeviceId)) {
                    executeTrezorTaskIfCan(TASK_CHANGE_SETTING_PREFIX + POSTFIX_COMMON, ChangePin.newBuilder().build());
                }
            }
        });
        switchPassphrase.button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (initializedTrezor != null && initializedTrezor.getFeatures().getDeviceId().equals(connectedTrezorDeviceId)) {
                    if (initializedTrezor.getFeatures().getPassphraseProtection()) {
                        CheckConfirmedDialog.show(getSupportFragmentManager(), null, DIALOG_DISABLE_PASSPHRASE, DIALOG_DISABLE_PASSPHRASE,
                                getString(R.string.warning),
                                getString(R.string.main_activity_disable_passphrase_prompt),
                                getString(R.string.i_understand),
                                getString(R.string.main_activity_disable_passphrase));
                    }
                    else {
                        executeTrezorTaskIfCan(TASK_CHANGE_SETTING_PREFIX + POSTFIX_COMMON, ApplySettings.newBuilder().setUsePassphrase(true).build());
                        refreshGui();
                    }
                }
            }
        });
//        btnForgetDevice.setOnClickListener(new OnClickListener() {
//            @Override
//            public void onClick(View view) {
//                PromptDialog.show(getSupportFragmentManager(), null, DIALOG_FORGET_DEVICE, DIALOG_FORGET_DEVICE, getString(R.string.main_activity_forget_device_title), getString(R.string.main_activity_forget_device_prompt),
//                        true, true, true, null, getString(R.string.main_activity_forget_device_title), getString(R.string.cancel));
//            }
//        });
        btnWipeDevice.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (initializedTrezor != null && initializedTrezor.getFeatures().getDeviceId().equals(connectedTrezorDeviceId)) {
                    CheckConfirmedDialog.show(getSupportFragmentManager(), null, DIALOG_WIPE, DIALOG_WIPE,
                            getString(R.string.warning),
                            CustomHtml.fromHtmlWithCustomSpans(CustomHtml.getFontColorTag(getString(R.string.main_activity_wipe_device_prompt_text), getResources().getColor(R.color.text_problem))),